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"
23 #include "wine/debug.h"
24 #include "wine/unicode.h"
28 #include "d3dcommon.h"
29 #include "d3dcompiler.h"
30 #include "d3dx9_36_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
34 /* This function is not declared in the SDK headers yet */
35 HRESULT WINAPI D3DAssemble(LPCVOID data, SIZE_T datasize, LPCSTR filename,
36 const D3D_SHADER_MACRO *defines, ID3DInclude *include,
38 ID3DBlob **shader, ID3DBlob **error_messages);
40 LPCSTR WINAPI D3DXGetPixelShaderProfile(LPDIRECT3DDEVICE9 device)
44 TRACE("device %p\n", device);
46 if (!device) return NULL;
48 IDirect3DDevice9_GetDeviceCaps(device,&caps);
50 switch (caps.PixelShaderVersion)
52 case D3DPS_VERSION(1, 1):
55 case D3DPS_VERSION(1, 2):
58 case D3DPS_VERSION(1, 3):
61 case D3DPS_VERSION(1, 4):
64 case D3DPS_VERSION(2, 0):
65 if ((caps.PS20Caps.NumTemps>=22) &&
66 (caps.PS20Caps.Caps&D3DPS20CAPS_ARBITRARYSWIZZLE) &&
67 (caps.PS20Caps.Caps&D3DPS20CAPS_GRADIENTINSTRUCTIONS) &&
68 (caps.PS20Caps.Caps&D3DPS20CAPS_PREDICATION) &&
69 (caps.PS20Caps.Caps&D3DPS20CAPS_NODEPENDENTREADLIMIT) &&
70 (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
74 if ((caps.PS20Caps.NumTemps>=32) &&
75 (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
81 case D3DPS_VERSION(3, 0):
88 UINT WINAPI D3DXGetShaderSize(const DWORD *byte_code)
90 const DWORD *ptr = byte_code;
92 TRACE("byte_code %p\n", byte_code);
96 /* Look for the END token, skipping the VERSION token */
97 while (*++ptr != D3DSIO_END)
100 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
102 ptr += ((*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT);
107 /* Return the shader size in bytes */
108 return (ptr - byte_code) * sizeof(*ptr);
111 DWORD WINAPI D3DXGetShaderVersion(const DWORD *byte_code)
113 TRACE("byte_code %p\n", byte_code);
115 return byte_code ? *byte_code : 0;
118 LPCSTR WINAPI D3DXGetVertexShaderProfile(LPDIRECT3DDEVICE9 device)
122 TRACE("device %p\n", device);
124 if (!device) return NULL;
126 IDirect3DDevice9_GetDeviceCaps(device,&caps);
128 switch (caps.VertexShaderVersion)
130 case D3DVS_VERSION(1, 1):
132 case D3DVS_VERSION(2, 0):
133 if ((caps.VS20Caps.NumTemps>=13) &&
134 (caps.VS20Caps.DynamicFlowControlDepth==24) &&
135 (caps.VS20Caps.Caps&D3DPS20CAPS_PREDICATION))
140 case D3DVS_VERSION(3, 0):
147 HRESULT WINAPI D3DXFindShaderComment(CONST DWORD* byte_code, DWORD fourcc, LPCVOID* data, UINT* size)
149 CONST DWORD *ptr = byte_code;
151 TRACE("(%p, %x, %p, %p)\n", byte_code, fourcc, data, size);
154 return D3DERR_INVALIDCALL;
156 while (*++ptr != D3DSIO_END)
158 /* Check if it is a comment */
159 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
161 DWORD comment_size = (*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
163 /* Check if this is the comment we are looking for */
164 if (*(ptr + 1) == fourcc)
166 UINT ctab_size = (comment_size - 1) * sizeof(DWORD);
167 LPCVOID ctab_data = ptr + 2;
172 TRACE("Returning comment data at %p with size %d\n", ctab_data, ctab_size);
182 HRESULT WINAPI D3DXAssembleShader(LPCSTR data,
184 CONST D3DXMACRO* defines,
185 LPD3DXINCLUDE include,
187 LPD3DXBUFFER* shader,
188 LPD3DXBUFFER* error_messages)
190 /* Forward to d3dcompiler: the parameter types aren't really different,
191 the actual data types are equivalent */
192 HRESULT hr = D3DAssemble(data, data_len, NULL, (D3D_SHADER_MACRO *)defines,
193 (ID3DInclude *)include, flags, (ID3DBlob **)shader,
194 (ID3DBlob **)error_messages);
196 if(hr == E_FAIL) hr = D3DXERR_INVALIDDATA;
200 /* D3DXInclude private implementation, used to implement
201 D3DXAssembleShaderFromFile from D3DXAssembleShader */
202 /* To be able to correctly resolve include search paths we have to store
203 the pathname of each include file. We store the pathname pointer right
204 before the file data. */
205 static HRESULT WINAPI d3dincludefromfile_open(ID3DXInclude *iface,
206 D3DXINCLUDE_TYPE include_type,
207 LPCSTR filename, LPCVOID parent_data,
208 LPCVOID *data, UINT *bytes) {
209 const char *p, *parent_name = "";
210 char *pathname = NULL;
211 char **buffer = NULL;
215 if(parent_data != NULL)
216 parent_name = *((const char **)parent_data - 1);
218 TRACE("Looking up for include file %s, parent %s\n", debugstr_a(filename), debugstr_a(parent_name));
220 if ((p = strrchr(parent_name, '\\')) || (p = strrchr(parent_name, '/'))) p++;
221 else p = parent_name;
222 pathname = HeapAlloc(GetProcessHeap(), 0, (p - parent_name) + strlen(filename) + 1);
224 return HRESULT_FROM_WIN32(GetLastError());
226 memcpy(pathname, parent_name, p - parent_name);
227 strcpy(pathname + (p - parent_name), filename);
229 file = CreateFileA(pathname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
230 if(file == INVALID_HANDLE_VALUE)
233 TRACE("Include file found at pathname = %s\n", debugstr_a(pathname));
235 size = GetFileSize(file, NULL);
236 if(size == INVALID_FILE_SIZE)
239 buffer = HeapAlloc(GetProcessHeap(), 0, size + sizeof(char *));
243 if(!ReadFile(file, buffer + 1, size, bytes, NULL))
253 HeapFree(GetProcessHeap(), 0, pathname);
254 HeapFree(GetProcessHeap(), 0, buffer);
255 return HRESULT_FROM_WIN32(GetLastError());
258 static HRESULT WINAPI d3dincludefromfile_close(ID3DXInclude *iface, LPCVOID data) {
259 HeapFree(GetProcessHeap(), 0, *((char **)data - 1));
260 HeapFree(GetProcessHeap(), 0, (char **)data - 1);
264 static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl = {
265 d3dincludefromfile_open,
266 d3dincludefromfile_close
269 struct D3DXIncludeImpl {
270 ID3DXInclude ID3DXInclude_iface;
273 HRESULT WINAPI D3DXAssembleShaderFromFileA(LPCSTR filename,
274 CONST D3DXMACRO* defines,
275 LPD3DXINCLUDE include,
277 LPD3DXBUFFER* shader,
278 LPD3DXBUFFER* error_messages)
280 LPWSTR filename_w = NULL;
284 if (!filename) return D3DXERR_INVALIDDATA;
286 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
287 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
288 if (!filename_w) return E_OUTOFMEMORY;
289 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
291 ret = D3DXAssembleShaderFromFileW(filename_w, defines, include, flags, shader, error_messages);
293 HeapFree(GetProcessHeap(), 0, filename_w);
297 HRESULT WINAPI D3DXAssembleShaderFromFileW(LPCWSTR filename,
298 CONST D3DXMACRO* defines,
299 LPD3DXINCLUDE include,
301 LPD3DXBUFFER* shader,
302 LPD3DXBUFFER* error_messages)
307 struct D3DXIncludeImpl includefromfile;
309 if(FAILED(map_view_of_file(filename, &buffer, &len)))
310 return D3DXERR_INVALIDDATA;
314 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
315 include = &includefromfile.ID3DXInclude_iface;
318 hr = D3DXAssembleShader(buffer, len, defines, include, flags,
319 shader, error_messages);
321 UnmapViewOfFile(buffer);
325 HRESULT WINAPI D3DXAssembleShaderFromResourceA(HMODULE module,
327 CONST D3DXMACRO* defines,
328 LPD3DXINCLUDE include,
330 LPD3DXBUFFER* shader,
331 LPD3DXBUFFER* error_messages)
337 if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
338 return D3DXERR_INVALIDDATA;
339 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
340 return D3DXERR_INVALIDDATA;
341 return D3DXAssembleShader(buffer, len, defines, include, flags,
342 shader, error_messages);
345 HRESULT WINAPI D3DXAssembleShaderFromResourceW(HMODULE module,
347 CONST D3DXMACRO* defines,
348 LPD3DXINCLUDE include,
350 LPD3DXBUFFER* shader,
351 LPD3DXBUFFER* error_messages)
357 if (!(res = FindResourceW(module, resource, (LPCWSTR)RT_RCDATA)))
358 return D3DXERR_INVALIDDATA;
359 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
360 return D3DXERR_INVALIDDATA;
361 return D3DXAssembleShader(buffer, len, defines, include, flags,
362 shader, error_messages);
365 HRESULT WINAPI D3DXCompileShader(LPCSTR pSrcData,
367 CONST D3DXMACRO* pDefines,
368 LPD3DXINCLUDE pInclude,
369 LPCSTR pFunctionName,
372 LPD3DXBUFFER* ppShader,
373 LPD3DXBUFFER* ppErrorMsgs,
374 LPD3DXCONSTANTTABLE * ppConstantTable)
376 HRESULT hr = D3DCompile(pSrcData, srcDataLen, NULL,
377 (D3D_SHADER_MACRO *)pDefines, (ID3DInclude *)pInclude,
378 pFunctionName, pProfile, Flags, 0,
379 (ID3DBlob **)ppShader, (ID3DBlob **)ppErrorMsgs);
381 if(SUCCEEDED(hr) && ppConstantTable)
382 return D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*ppShader),
387 HRESULT WINAPI D3DXCompileShaderFromFileA(LPCSTR filename,
388 CONST D3DXMACRO* defines,
389 LPD3DXINCLUDE include,
393 LPD3DXBUFFER* shader,
394 LPD3DXBUFFER* error_messages,
395 LPD3DXCONSTANTTABLE* constant_table)
397 LPWSTR filename_w = NULL;
401 if (!filename) return D3DXERR_INVALIDDATA;
403 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
404 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
405 if (!filename_w) return E_OUTOFMEMORY;
406 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
408 ret = D3DXCompileShaderFromFileW(filename_w, defines, include,
409 entrypoint, profile, flags,
410 shader, error_messages, constant_table);
412 HeapFree(GetProcessHeap(), 0, filename_w);
416 HRESULT WINAPI D3DXCompileShaderFromFileW(LPCWSTR filename,
417 CONST D3DXMACRO* defines,
418 LPD3DXINCLUDE include,
422 LPD3DXBUFFER* shader,
423 LPD3DXBUFFER* error_messages,
424 LPD3DXCONSTANTTABLE* constant_table)
427 DWORD len, filename_len;
429 struct D3DXIncludeImpl includefromfile;
432 if (FAILED(map_view_of_file(filename, &buffer, &len)))
433 return D3DXERR_INVALIDDATA;
437 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
438 include = &includefromfile.ID3DXInclude_iface;
441 filename_len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
442 filename_a = HeapAlloc(GetProcessHeap(), 0, filename_len * sizeof(char));
445 UnmapViewOfFile(buffer);
446 return E_OUTOFMEMORY;
448 WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, filename_len, NULL, NULL);
450 hr = D3DCompile(buffer, len, filename_a, (const D3D_SHADER_MACRO *)defines,
451 (ID3DInclude *)include, entrypoint, profile, flags, 0,
452 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
454 if (SUCCEEDED(hr) && constant_table)
455 hr = D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader),
458 HeapFree(GetProcessHeap(), 0, filename_a);
459 UnmapViewOfFile(buffer);
463 HRESULT WINAPI D3DXCompileShaderFromResourceA(HMODULE module,
465 CONST D3DXMACRO* defines,
466 LPD3DXINCLUDE include,
470 LPD3DXBUFFER* shader,
471 LPD3DXBUFFER* error_messages,
472 LPD3DXCONSTANTTABLE* constant_table)
478 if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
479 return D3DXERR_INVALIDDATA;
480 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
481 return D3DXERR_INVALIDDATA;
482 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
483 flags, shader, error_messages, constant_table);
486 HRESULT WINAPI D3DXCompileShaderFromResourceW(HMODULE module,
488 CONST D3DXMACRO* defines,
489 LPD3DXINCLUDE include,
493 LPD3DXBUFFER* shader,
494 LPD3DXBUFFER* error_messages,
495 LPD3DXCONSTANTTABLE* constant_table)
501 if (!(res = FindResourceW(module, resource, (LPCWSTR)RT_RCDATA)))
502 return D3DXERR_INVALIDDATA;
503 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
504 return D3DXERR_INVALIDDATA;
505 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
506 flags, shader, error_messages, constant_table);
509 HRESULT WINAPI D3DXPreprocessShader(LPCSTR data,
511 CONST D3DXMACRO* defines,
512 LPD3DXINCLUDE include,
513 LPD3DXBUFFER* shader,
514 LPD3DXBUFFER* error_messages)
516 TRACE("Forward to D3DPreprocess\n");
517 return D3DPreprocess(data, data_len, NULL,
518 (const D3D_SHADER_MACRO *)defines, (ID3DInclude *)include,
519 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
522 HRESULT WINAPI D3DXPreprocessShaderFromFileA(LPCSTR filename,
523 CONST D3DXMACRO* defines,
524 LPD3DXINCLUDE include,
525 LPD3DXBUFFER* shader,
526 LPD3DXBUFFER* error_messages)
528 WCHAR *filename_w = NULL;
532 if (!filename) return D3DXERR_INVALIDDATA;
534 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
535 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
536 if (!filename_w) return E_OUTOFMEMORY;
537 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
539 ret = D3DXPreprocessShaderFromFileW(filename_w, defines, include, shader, error_messages);
541 HeapFree(GetProcessHeap(), 0, filename_w);
545 HRESULT WINAPI D3DXPreprocessShaderFromFileW(LPCWSTR filename,
546 CONST D3DXMACRO* defines,
547 LPD3DXINCLUDE include,
548 LPD3DXBUFFER* shader,
549 LPD3DXBUFFER* error_messages)
554 struct D3DXIncludeImpl includefromfile;
556 if (FAILED(map_view_of_file(filename, &buffer, &len)))
557 return D3DXERR_INVALIDDATA;
561 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
562 include = &includefromfile.ID3DXInclude_iface;
565 hr = D3DPreprocess(buffer, len, NULL,
566 (const D3D_SHADER_MACRO *)defines,
567 (ID3DInclude *) include,
568 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
570 UnmapViewOfFile(buffer);
574 HRESULT WINAPI D3DXPreprocessShaderFromResourceA(HMODULE module,
576 CONST D3DXMACRO* defines,
577 LPD3DXINCLUDE include,
578 LPD3DXBUFFER* shader,
579 LPD3DXBUFFER* error_messages)
585 if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
586 return D3DXERR_INVALIDDATA;
587 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
588 return D3DXERR_INVALIDDATA;
589 return D3DXPreprocessShader(buffer, len, defines, include,
590 shader, error_messages);
593 HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module,
595 CONST D3DXMACRO* defines,
596 LPD3DXINCLUDE include,
597 LPD3DXBUFFER* shader,
598 LPD3DXBUFFER* error_messages)
604 if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
605 return D3DXERR_INVALIDDATA;
606 if (FAILED(load_resource_into_memory(module, res, (void **)&buffer, &len)))
607 return D3DXERR_INVALIDDATA;
608 return D3DXPreprocessShader(buffer, len, defines, include,
609 shader, error_messages);
613 typedef struct ctab_constant {
614 D3DXCONSTANT_DESC desc;
615 struct ctab_constant *members;
618 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl;
620 typedef struct ID3DXConstantTableImpl {
621 ID3DXConstantTable ID3DXConstantTable_iface;
625 D3DXCONSTANTTABLE_DESC desc;
626 ctab_constant *constants;
627 } ID3DXConstantTableImpl;
629 static inline ID3DXConstantTableImpl *impl_from_ID3DXConstantTable(ID3DXConstantTable *iface)
631 return CONTAINING_RECORD(iface, ID3DXConstantTableImpl, ID3DXConstantTable_iface);
634 static inline int is_vertex_shader(DWORD version)
636 return (version & 0xFFFF0000) == 0xFFFE0000;
639 /*** IUnknown methods ***/
640 static HRESULT WINAPI ID3DXConstantTableImpl_QueryInterface(ID3DXConstantTable* iface, REFIID riid, void** ppvObject)
642 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
644 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
646 if (IsEqualGUID(riid, &IID_IUnknown) ||
647 IsEqualGUID(riid, &IID_ID3DXBuffer) ||
648 IsEqualGUID(riid, &IID_ID3DXConstantTable))
650 ID3DXConstantTable_AddRef(iface);
655 WARN("Interface %s not found.\n", debugstr_guid(riid));
657 return E_NOINTERFACE;
660 static ULONG WINAPI ID3DXConstantTableImpl_AddRef(ID3DXConstantTable* iface)
662 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
664 TRACE("(%p)->(): AddRef from %d\n", This, This->ref);
666 return InterlockedIncrement(&This->ref);
669 static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable* iface)
671 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
672 ULONG ref = InterlockedDecrement(&This->ref);
674 TRACE("(%p)->(): Release from %d\n", This, ref + 1);
678 HeapFree(GetProcessHeap(), 0, This->constants);
679 HeapFree(GetProcessHeap(), 0, This->ctab);
680 HeapFree(GetProcessHeap(), 0, This);
686 /*** ID3DXBuffer methods ***/
687 static LPVOID WINAPI ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable* iface)
689 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
691 TRACE("(%p)->()\n", This);
696 static DWORD WINAPI ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable* iface)
698 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
700 TRACE("(%p)->()\n", This);
705 /*** ID3DXConstantTable methods ***/
706 static HRESULT WINAPI ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable* iface, D3DXCONSTANTTABLE_DESC *desc)
708 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
710 TRACE("(%p)->(%p)\n", This, desc);
713 return D3DERR_INVALIDCALL;
715 memcpy(desc, &This->desc, sizeof(This->desc));
720 static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable* iface, D3DXHANDLE constant,
721 D3DXCONSTANT_DESC *desc, UINT *count)
723 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
724 ctab_constant *constant_info;
726 TRACE("(%p)->(%p, %p, %p)\n", This, constant, desc, count);
729 return D3DERR_INVALIDCALL;
731 /* Applications can pass the name of the constant in place of the handle */
732 if (!((UINT_PTR)constant >> 16))
733 constant_info = &This->constants[(UINT_PTR)constant - 1];
736 D3DXHANDLE c = ID3DXConstantTable_GetConstantByName(iface, NULL, constant);
738 return D3DERR_INVALIDCALL;
740 constant_info = &This->constants[(UINT_PTR)c - 1];
744 *desc = constant_info->desc;
751 static UINT WINAPI ID3DXConstantTableImpl_GetSamplerIndex(ID3DXConstantTable *iface, D3DXHANDLE constant)
753 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
754 D3DXCONSTANT_DESC desc;
758 TRACE("(%p)->(%p)\n", This, constant);
760 res = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &count);
764 if (desc.RegisterSet != D3DXRS_SAMPLER)
767 return desc.RegisterIndex;
770 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable* iface, D3DXHANDLE constant, UINT index)
772 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
774 TRACE("(%p)->(%p, %d)\n", This, constant, index);
778 FIXME("Only top level constants supported\n");
782 if (index >= This->desc.Constants)
785 return (D3DXHANDLE)(DWORD_PTR)(index + 1);
788 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable* iface, D3DXHANDLE constant, LPCSTR name)
790 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
793 TRACE("(%p)->(%p, %s)\n", This, constant, name);
800 FIXME("Only top level constants supported\n");
804 for (i = 0; i < This->desc.Constants; i++)
805 if (!strcmp(This->constants[i].desc.Name, name))
806 return (D3DXHANDLE)(DWORD_PTR)(i + 1);
811 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable* iface, D3DXHANDLE constant, UINT index)
813 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
815 FIXME("(%p)->(%p, %d): stub\n", This, constant, index);
820 static HRESULT set_float_array(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device, D3DXHANDLE constant, const void *data,
821 UINT count, D3DXPARAMETER_TYPE type)
823 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
825 D3DXCONSTANT_DESC desc;
827 UINT i, desc_count = 1;
828 float row[4] = {0.0f, 0.0f, 0.0f, 0.0f};
830 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
833 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x", hr);
834 return D3DERR_INVALIDCALL;
837 switch (desc.RegisterSet)
840 for (i = 0; i < count && i < desc.RegisterCount; i++)
842 /* We need the for loop since each IDirect3DDevice9_Set*ShaderConstantF expects a float4 */
846 row[0] = ((float *)data)[i];
849 row[0] = (float)((int *)data)[i];
852 FIXME("Unhandled type passed to set_float_array\n");
853 return D3DERR_INVALIDCALL;
855 if (is_vertex_shader(This->desc.Version))
856 IDirect3DDevice9_SetVertexShaderConstantF(device, desc.RegisterIndex + i, row, 1);
858 IDirect3DDevice9_SetPixelShaderConstantF(device, desc.RegisterIndex + i, row, 1);
862 FIXME("Handle other register sets\n");
869 static HRESULT WINAPI ID3DXConstantTableImpl_SetDefaults(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device)
871 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
873 FIXME("(%p)->(%p): stub\n", This, device);
878 static HRESULT WINAPI ID3DXConstantTableImpl_SetValue(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
879 D3DXHANDLE constant, LPCVOID data, UINT bytes)
881 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
883 FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, data, bytes);
888 static HRESULT WINAPI ID3DXConstantTableImpl_SetBool(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
889 D3DXHANDLE constant, BOOL b)
891 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
893 FIXME("(%p)->(%p, %p, %d): stub\n", This, device, constant, b);
898 static HRESULT WINAPI ID3DXConstantTableImpl_SetBoolArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
899 D3DXHANDLE constant, CONST BOOL* b, UINT count)
901 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
903 FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, b, count);
908 static HRESULT WINAPI ID3DXConstantTableImpl_SetInt(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device, D3DXHANDLE constant, INT n)
910 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
912 TRACE("(%p)->(%p, %p, %d)\n", This, device, constant, n);
914 return ID3DXConstantTable_SetIntArray(iface, device, constant, &n, 1);
917 static HRESULT WINAPI ID3DXConstantTableImpl_SetIntArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
918 D3DXHANDLE constant, CONST INT* n, UINT count)
920 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
922 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, n, count);
924 return set_float_array(iface, device, constant, n, count, D3DXPT_INT);
927 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloat(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
928 D3DXHANDLE constant, FLOAT f)
930 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
932 TRACE("(%p)->(%p, %p, %f)\n", This, device, constant, f);
934 return ID3DXConstantTable_SetFloatArray(iface, device, constant, &f, 1);
937 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloatArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
938 D3DXHANDLE constant, CONST FLOAT *f, UINT count)
940 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
942 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, f, count);
944 return set_float_array(iface, device, constant, f, count, D3DXPT_FLOAT);
947 static HRESULT WINAPI ID3DXConstantTableImpl_SetVector(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
948 D3DXHANDLE constant, CONST D3DXVECTOR4 *vector)
950 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
952 TRACE("(%p)->(%p, %p, %p)\n", This, device, constant, vector);
954 return ID3DXConstantTable_SetVectorArray(iface, device, constant, vector, 1);
957 static HRESULT WINAPI ID3DXConstantTableImpl_SetVectorArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
958 D3DXHANDLE constant, CONST D3DXVECTOR4 *vector, UINT count)
960 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
962 D3DXCONSTANT_DESC desc;
966 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, vector, count);
968 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
971 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x", hr);
972 return D3DERR_INVALIDCALL;
975 switch (desc.RegisterSet)
978 if (is_vertex_shader(This->desc.Version))
979 IDirect3DDevice9_SetVertexShaderConstantF(device, desc.RegisterIndex, (float *)vector,
980 min(desc.RegisterCount, count));
982 IDirect3DDevice9_SetPixelShaderConstantF(device, desc.RegisterIndex, (float *)vector,
983 min(desc.RegisterCount, count));
986 FIXME("Handle other register sets\n");
993 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrix(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
994 D3DXHANDLE constant, CONST D3DXMATRIX *matrix)
996 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
998 TRACE("(%p)->(%p, %p, %p)\n", This, device, constant, matrix);
1000 return ID3DXConstantTable_SetMatrixArray(iface, device, constant, matrix, 1);
1003 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
1004 D3DXHANDLE constant, CONST D3DXMATRIX *matrix, UINT count)
1006 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1008 D3DXCONSTANT_DESC desc;
1010 UINT i, desc_count = 1;
1013 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, matrix, count);
1015 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
1018 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x", hr);
1019 return D3DERR_INVALIDCALL;
1022 switch (desc.RegisterSet)
1025 /* i * 4 + 3 is the last register we set. The conditional makes sure that we don't access
1026 registers we're not supposed to */
1027 for (i = 0; i < count && i * 4 + 3 < desc.RegisterCount; i++)
1029 if (desc.Class == D3DXPC_MATRIX_ROWS)
1032 D3DXMatrixTranspose(&temp, &matrix[i]);
1034 if (is_vertex_shader(This->desc.Version))
1035 IDirect3DDevice9_SetVertexShaderConstantF(device, desc.RegisterIndex + i * 4, &temp._11, 4);
1037 IDirect3DDevice9_SetPixelShaderConstantF(device, desc.RegisterIndex + i * 4, &temp._11, 4);
1041 FIXME("Handle other register sets\n");
1048 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixPointerArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
1049 D3DXHANDLE constant, CONST D3DXMATRIX** matrix, UINT count)
1051 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1053 FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
1058 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTranspose(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
1059 D3DXHANDLE constant, CONST D3DXMATRIX* matrix)
1061 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1063 FIXME("(%p)->(%p, %p, %p): stub\n", This, device, constant, matrix);
1068 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposeArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
1069 D3DXHANDLE constant, CONST D3DXMATRIX* matrix, UINT count)
1071 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1073 FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
1078 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposePointerArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
1079 D3DXHANDLE constant, CONST D3DXMATRIX** matrix, UINT count)
1081 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1083 FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
1088 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl =
1090 /*** IUnknown methods ***/
1091 ID3DXConstantTableImpl_QueryInterface,
1092 ID3DXConstantTableImpl_AddRef,
1093 ID3DXConstantTableImpl_Release,
1094 /*** ID3DXBuffer methods ***/
1095 ID3DXConstantTableImpl_GetBufferPointer,
1096 ID3DXConstantTableImpl_GetBufferSize,
1097 /*** ID3DXConstantTable methods ***/
1098 ID3DXConstantTableImpl_GetDesc,
1099 ID3DXConstantTableImpl_GetConstantDesc,
1100 ID3DXConstantTableImpl_GetSamplerIndex,
1101 ID3DXConstantTableImpl_GetConstant,
1102 ID3DXConstantTableImpl_GetConstantByName,
1103 ID3DXConstantTableImpl_GetConstantElement,
1104 ID3DXConstantTableImpl_SetDefaults,
1105 ID3DXConstantTableImpl_SetValue,
1106 ID3DXConstantTableImpl_SetBool,
1107 ID3DXConstantTableImpl_SetBoolArray,
1108 ID3DXConstantTableImpl_SetInt,
1109 ID3DXConstantTableImpl_SetIntArray,
1110 ID3DXConstantTableImpl_SetFloat,
1111 ID3DXConstantTableImpl_SetFloatArray,
1112 ID3DXConstantTableImpl_SetVector,
1113 ID3DXConstantTableImpl_SetVectorArray,
1114 ID3DXConstantTableImpl_SetMatrix,
1115 ID3DXConstantTableImpl_SetMatrixArray,
1116 ID3DXConstantTableImpl_SetMatrixPointerArray,
1117 ID3DXConstantTableImpl_SetMatrixTranspose,
1118 ID3DXConstantTableImpl_SetMatrixTransposeArray,
1119 ID3DXConstantTableImpl_SetMatrixTransposePointerArray
1122 static HRESULT parse_ctab_constant_type(const D3DXSHADER_TYPEINFO *type, ctab_constant *constant)
1124 constant->desc.Class = type->Class;
1125 constant->desc.Type = type->Type;
1126 constant->desc.Rows = type->Rows;
1127 constant->desc.Columns = type->Columns;
1128 constant->desc.Elements = type->Elements;
1129 constant->desc.StructMembers = type->StructMembers;
1131 TRACE("class = %d, type = %d, rows = %d, columns = %d, elements = %d, struct_members = %d\n",
1132 constant->desc.Class, constant->desc.Type, constant->desc.Elements,
1133 constant->desc.Rows, constant->desc.Columns, constant->desc.StructMembers);
1135 if ((constant->desc.Class == D3DXPC_STRUCT) && constant->desc.StructMembers)
1137 FIXME("Struct not supported yet\n");
1144 HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code,
1146 LPD3DXCONSTANTTABLE* constant_table)
1148 ID3DXConstantTableImpl* object = NULL;
1152 const D3DXSHADER_CONSTANTTABLE* ctab_header;
1153 D3DXSHADER_CONSTANTINFO* constant_info;
1156 TRACE("(%p, %x, %p)\n", byte_code, flags, constant_table);
1158 if (!byte_code || !constant_table)
1159 return D3DERR_INVALIDCALL;
1161 hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), &data, &size);
1163 return D3DXERR_INVALIDDATA;
1165 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ID3DXConstantTableImpl));
1168 ERR("Out of memory\n");
1169 return E_OUTOFMEMORY;
1172 object->ID3DXConstantTable_iface.lpVtbl = &ID3DXConstantTable_Vtbl;
1175 if (size < sizeof(D3DXSHADER_CONSTANTTABLE))
1177 hr = D3DXERR_INVALIDDATA;
1181 object->ctab = HeapAlloc(GetProcessHeap(), 0, size);
1184 ERR("Out of memory\n");
1188 object->size = size;
1189 memcpy(object->ctab, data, object->size);
1191 ctab_header = (const D3DXSHADER_CONSTANTTABLE*)data;
1192 if (ctab_header->Size != sizeof(D3DXSHADER_CONSTANTTABLE))
1194 hr = D3DXERR_INVALIDDATA;
1197 object->desc.Creator = ctab_header->Creator ? object->ctab + ctab_header->Creator : NULL;
1198 object->desc.Version = ctab_header->Version;
1199 object->desc.Constants = ctab_header->Constants;
1200 if (object->desc.Creator)
1201 TRACE("Creator = %s\n", object->desc.Creator);
1202 TRACE("Version = %x\n", object->desc.Version);
1203 TRACE("Constants = %d\n", ctab_header->Constants);
1204 if (ctab_header->Target)
1205 TRACE("Target = %s\n", object->ctab + ctab_header->Target);
1207 if (object->desc.Constants > 65535)
1209 FIXME("Too many constants (%u)\n", object->desc.Constants);
1214 object->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1215 sizeof(*object->constants) * object->desc.Constants);
1216 if (!object->constants)
1218 ERR("Out of memory\n");
1223 constant_info = (LPD3DXSHADER_CONSTANTINFO)(object->ctab + ctab_header->ConstantInfo);
1224 for (i = 0; i < ctab_header->Constants; i++)
1226 TRACE("name = %s\n", object->ctab + constant_info[i].Name);
1227 object->constants[i].desc.Name = object->ctab + constant_info[i].Name;
1228 object->constants[i].desc.RegisterSet = constant_info[i].RegisterSet;
1229 object->constants[i].desc.RegisterIndex = constant_info[i].RegisterIndex;
1230 object->constants[i].desc.RegisterCount = constant_info[i].RegisterCount;
1231 object->constants[i].desc.DefaultValue = object->ctab + constant_info[i].DefaultValue;
1233 hr = parse_ctab_constant_type((LPD3DXSHADER_TYPEINFO)(object->ctab + constant_info[i].TypeInfo),
1234 &object->constants[i]);
1238 if (constant_info[i].RegisterSet != D3DXRS_FLOAT4 &&
1239 constant_info[i].RegisterSet != D3DXRS_SAMPLER)
1240 FIXME("Don't know how to calculate Bytes for constants of type %d\n",
1241 constant_info[i].RegisterSet);
1244 * D3DXRS_FLOAT4 and D3DXRS_SAMPLER have a base size of 4
1245 * (not taking into account dimensions and element count)
1247 object->constants[i].desc.Bytes = 4;
1249 /* Take into account dimensions and elements */
1250 object->constants[i].desc.Bytes *= object->constants[i].desc.Elements;
1251 object->constants[i].desc.Bytes *= object->constants[i].desc.Rows *
1252 object->constants[i].desc.Columns;
1255 *constant_table = &object->ID3DXConstantTable_iface;
1261 HeapFree(GetProcessHeap(), 0, object->constants);
1262 HeapFree(GetProcessHeap(), 0, object->ctab);
1263 HeapFree(GetProcessHeap(), 0, object);
1268 HRESULT WINAPI D3DXGetShaderConstantTable(CONST DWORD* byte_code,
1269 LPD3DXCONSTANTTABLE* constant_table)
1271 TRACE("(%p, %p): Forwarded to D3DXGetShaderConstantTableEx\n", byte_code, constant_table);
1273 return D3DXGetShaderConstantTableEx(byte_code, 0, constant_table);