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 LPCSTR WINAPI D3DXGetPixelShaderProfile(LPDIRECT3DDEVICE9 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 LPCSTR WINAPI D3DXGetVertexShaderProfile(LPDIRECT3DDEVICE9 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);
157 return D3DERR_INVALIDCALL;
159 while (*++ptr != D3DSIO_END)
161 /* Check if it is a comment */
162 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
164 DWORD comment_size = (*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
166 /* Check if this is the comment we are looking for */
167 if (*(ptr + 1) == fourcc)
169 UINT ctab_size = (comment_size - 1) * sizeof(DWORD);
170 LPCVOID ctab_data = ptr + 2;
175 TRACE("Returning comment data at %p with size %d\n", ctab_data, ctab_size);
185 HRESULT WINAPI D3DXAssembleShader(LPCSTR data,
187 CONST D3DXMACRO* defines,
188 LPD3DXINCLUDE include,
190 LPD3DXBUFFER* shader,
191 LPD3DXBUFFER* error_messages)
193 /* Forward to d3dcompiler: the parameter types aren't really different,
194 the actual data types are equivalent */
195 HRESULT hr = D3DAssemble(data, data_len, NULL, (D3D_SHADER_MACRO *)defines,
196 (ID3DInclude *)include, flags, (ID3DBlob **)shader,
197 (ID3DBlob **)error_messages);
199 if(hr == E_FAIL) hr = D3DXERR_INVALIDDATA;
203 /* D3DXInclude private implementation, used to implement
204 D3DXAssembleShaderFromFile from D3DXAssembleShader */
205 /* To be able to correctly resolve include search paths we have to store
206 the pathname of each include file. We store the pathname pointer right
207 before the file data. */
208 static HRESULT WINAPI d3dincludefromfile_open(ID3DXInclude *iface,
209 D3DXINCLUDE_TYPE include_type,
210 LPCSTR filename, LPCVOID parent_data,
211 LPCVOID *data, UINT *bytes) {
212 const char *p, *parent_name = "";
213 char *pathname = NULL;
214 char **buffer = NULL;
218 if(parent_data != NULL)
219 parent_name = *((const char **)parent_data - 1);
221 TRACE("Looking up for include file %s, parent %s\n", debugstr_a(filename), debugstr_a(parent_name));
223 if ((p = strrchr(parent_name, '\\')) || (p = strrchr(parent_name, '/'))) p++;
224 else p = parent_name;
225 pathname = HeapAlloc(GetProcessHeap(), 0, (p - parent_name) + strlen(filename) + 1);
227 return HRESULT_FROM_WIN32(GetLastError());
229 memcpy(pathname, parent_name, p - parent_name);
230 strcpy(pathname + (p - parent_name), filename);
232 file = CreateFileA(pathname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
233 if(file == INVALID_HANDLE_VALUE)
236 TRACE("Include file found at pathname = %s\n", debugstr_a(pathname));
238 size = GetFileSize(file, NULL);
239 if(size == INVALID_FILE_SIZE)
242 buffer = HeapAlloc(GetProcessHeap(), 0, size + sizeof(char *));
246 if(!ReadFile(file, buffer + 1, size, bytes, NULL))
256 HeapFree(GetProcessHeap(), 0, pathname);
257 HeapFree(GetProcessHeap(), 0, buffer);
258 return HRESULT_FROM_WIN32(GetLastError());
261 static HRESULT WINAPI d3dincludefromfile_close(ID3DXInclude *iface, LPCVOID data) {
262 HeapFree(GetProcessHeap(), 0, *((char **)data - 1));
263 HeapFree(GetProcessHeap(), 0, (char **)data - 1);
267 static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl = {
268 d3dincludefromfile_open,
269 d3dincludefromfile_close
272 struct D3DXIncludeImpl {
273 ID3DXInclude ID3DXInclude_iface;
276 HRESULT WINAPI D3DXAssembleShaderFromFileA(LPCSTR filename,
277 CONST D3DXMACRO* defines,
278 LPD3DXINCLUDE include,
280 LPD3DXBUFFER* shader,
281 LPD3DXBUFFER* error_messages)
283 LPWSTR filename_w = NULL;
287 if (!filename) return D3DXERR_INVALIDDATA;
289 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
290 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
291 if (!filename_w) return E_OUTOFMEMORY;
292 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
294 ret = D3DXAssembleShaderFromFileW(filename_w, defines, include, flags, shader, error_messages);
296 HeapFree(GetProcessHeap(), 0, filename_w);
300 HRESULT WINAPI D3DXAssembleShaderFromFileW(LPCWSTR filename,
301 CONST D3DXMACRO* defines,
302 LPD3DXINCLUDE include,
304 LPD3DXBUFFER* shader,
305 LPD3DXBUFFER* error_messages)
310 struct D3DXIncludeImpl includefromfile;
312 if(FAILED(map_view_of_file(filename, &buffer, &len)))
313 return D3DXERR_INVALIDDATA;
317 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
318 include = &includefromfile.ID3DXInclude_iface;
321 hr = D3DXAssembleShader(buffer, len, defines, include, flags,
322 shader, error_messages);
324 UnmapViewOfFile(buffer);
328 HRESULT WINAPI D3DXAssembleShaderFromResourceA(HMODULE module,
330 CONST D3DXMACRO* defines,
331 LPD3DXINCLUDE include,
333 LPD3DXBUFFER* shader,
334 LPD3DXBUFFER* error_messages)
340 if (!(res = FindResourceA(module, resource, (LPCSTR)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 D3DXAssembleShaderFromResourceW(HMODULE module,
350 CONST D3DXMACRO* defines,
351 LPD3DXINCLUDE include,
353 LPD3DXBUFFER* shader,
354 LPD3DXBUFFER* error_messages)
360 if (!(res = FindResourceW(module, resource, (LPCWSTR)RT_RCDATA)))
361 return D3DXERR_INVALIDDATA;
362 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
363 return D3DXERR_INVALIDDATA;
364 return D3DXAssembleShader(buffer, len, defines, include, flags,
365 shader, error_messages);
368 HRESULT WINAPI D3DXCompileShader(LPCSTR pSrcData,
370 CONST D3DXMACRO* pDefines,
371 LPD3DXINCLUDE pInclude,
372 LPCSTR pFunctionName,
375 LPD3DXBUFFER* ppShader,
376 LPD3DXBUFFER* ppErrorMsgs,
377 LPD3DXCONSTANTTABLE * ppConstantTable)
379 HRESULT hr = D3DCompile(pSrcData, srcDataLen, NULL,
380 (D3D_SHADER_MACRO *)pDefines, (ID3DInclude *)pInclude,
381 pFunctionName, pProfile, Flags, 0,
382 (ID3DBlob **)ppShader, (ID3DBlob **)ppErrorMsgs);
384 if(SUCCEEDED(hr) && ppConstantTable)
385 return D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*ppShader),
390 HRESULT WINAPI D3DXCompileShaderFromFileA(LPCSTR filename,
391 CONST D3DXMACRO* defines,
392 LPD3DXINCLUDE include,
396 LPD3DXBUFFER* shader,
397 LPD3DXBUFFER* error_messages,
398 LPD3DXCONSTANTTABLE* constant_table)
400 LPWSTR filename_w = NULL;
404 if (!filename) return D3DXERR_INVALIDDATA;
406 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
407 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
408 if (!filename_w) return E_OUTOFMEMORY;
409 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
411 ret = D3DXCompileShaderFromFileW(filename_w, defines, include,
412 entrypoint, profile, flags,
413 shader, error_messages, constant_table);
415 HeapFree(GetProcessHeap(), 0, filename_w);
419 HRESULT WINAPI D3DXCompileShaderFromFileW(LPCWSTR filename,
420 CONST D3DXMACRO* defines,
421 LPD3DXINCLUDE include,
425 LPD3DXBUFFER* shader,
426 LPD3DXBUFFER* error_messages,
427 LPD3DXCONSTANTTABLE* constant_table)
430 DWORD len, filename_len;
432 struct D3DXIncludeImpl includefromfile;
435 if (FAILED(map_view_of_file(filename, &buffer, &len)))
436 return D3DXERR_INVALIDDATA;
440 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
441 include = &includefromfile.ID3DXInclude_iface;
444 filename_len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
445 filename_a = HeapAlloc(GetProcessHeap(), 0, filename_len * sizeof(char));
448 UnmapViewOfFile(buffer);
449 return E_OUTOFMEMORY;
451 WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, filename_len, NULL, NULL);
453 hr = D3DCompile(buffer, len, filename_a, (const D3D_SHADER_MACRO *)defines,
454 (ID3DInclude *)include, entrypoint, profile, flags, 0,
455 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
457 if (SUCCEEDED(hr) && constant_table)
458 hr = D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader),
461 HeapFree(GetProcessHeap(), 0, filename_a);
462 UnmapViewOfFile(buffer);
466 HRESULT WINAPI D3DXCompileShaderFromResourceA(HMODULE module,
468 CONST D3DXMACRO* defines,
469 LPD3DXINCLUDE include,
473 LPD3DXBUFFER* shader,
474 LPD3DXBUFFER* error_messages,
475 LPD3DXCONSTANTTABLE* constant_table)
481 if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
482 return D3DXERR_INVALIDDATA;
483 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
484 return D3DXERR_INVALIDDATA;
485 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
486 flags, shader, error_messages, constant_table);
489 HRESULT WINAPI D3DXCompileShaderFromResourceW(HMODULE module,
491 CONST D3DXMACRO* defines,
492 LPD3DXINCLUDE include,
496 LPD3DXBUFFER* shader,
497 LPD3DXBUFFER* error_messages,
498 LPD3DXCONSTANTTABLE* constant_table)
504 if (!(res = FindResourceW(module, resource, (LPCWSTR)RT_RCDATA)))
505 return D3DXERR_INVALIDDATA;
506 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
507 return D3DXERR_INVALIDDATA;
508 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
509 flags, shader, error_messages, constant_table);
512 HRESULT WINAPI D3DXPreprocessShader(LPCSTR data,
514 CONST D3DXMACRO* defines,
515 LPD3DXINCLUDE include,
516 LPD3DXBUFFER* shader,
517 LPD3DXBUFFER* error_messages)
519 TRACE("Forward to D3DPreprocess\n");
520 return D3DPreprocess(data, data_len, NULL,
521 (const D3D_SHADER_MACRO *)defines, (ID3DInclude *)include,
522 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
525 HRESULT WINAPI D3DXPreprocessShaderFromFileA(LPCSTR filename,
526 CONST D3DXMACRO* defines,
527 LPD3DXINCLUDE include,
528 LPD3DXBUFFER* shader,
529 LPD3DXBUFFER* error_messages)
531 WCHAR *filename_w = NULL;
535 if (!filename) return D3DXERR_INVALIDDATA;
537 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
538 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
539 if (!filename_w) return E_OUTOFMEMORY;
540 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
542 ret = D3DXPreprocessShaderFromFileW(filename_w, defines, include, shader, error_messages);
544 HeapFree(GetProcessHeap(), 0, filename_w);
548 HRESULT WINAPI D3DXPreprocessShaderFromFileW(LPCWSTR filename,
549 CONST D3DXMACRO* defines,
550 LPD3DXINCLUDE include,
551 LPD3DXBUFFER* shader,
552 LPD3DXBUFFER* error_messages)
557 struct D3DXIncludeImpl includefromfile;
559 if (FAILED(map_view_of_file(filename, &buffer, &len)))
560 return D3DXERR_INVALIDDATA;
564 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
565 include = &includefromfile.ID3DXInclude_iface;
568 hr = D3DPreprocess(buffer, len, NULL,
569 (const D3D_SHADER_MACRO *)defines,
570 (ID3DInclude *) include,
571 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
573 UnmapViewOfFile(buffer);
577 HRESULT WINAPI D3DXPreprocessShaderFromResourceA(HMODULE module,
579 CONST D3DXMACRO* defines,
580 LPD3DXINCLUDE include,
581 LPD3DXBUFFER* shader,
582 LPD3DXBUFFER* error_messages)
588 if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
589 return D3DXERR_INVALIDDATA;
590 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
591 return D3DXERR_INVALIDDATA;
592 return D3DXPreprocessShader(buffer, len, defines, include,
593 shader, error_messages);
596 HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module,
598 CONST D3DXMACRO* defines,
599 LPD3DXINCLUDE include,
600 LPD3DXBUFFER* shader,
601 LPD3DXBUFFER* error_messages)
607 if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
608 return D3DXERR_INVALIDDATA;
609 if (FAILED(load_resource_into_memory(module, res, (void **)&buffer, &len)))
610 return D3DXERR_INVALIDDATA;
611 return D3DXPreprocessShader(buffer, len, defines, include,
612 shader, error_messages);
616 typedef struct ctab_constant {
617 D3DXCONSTANT_DESC desc;
618 struct ctab_constant *members;
621 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl;
623 typedef struct ID3DXConstantTableImpl {
624 ID3DXConstantTable ID3DXConstantTable_iface;
628 D3DXCONSTANTTABLE_DESC desc;
629 ctab_constant *constants;
630 } ID3DXConstantTableImpl;
632 static inline ID3DXConstantTableImpl *impl_from_ID3DXConstantTable(ID3DXConstantTable *iface)
634 return CONTAINING_RECORD(iface, ID3DXConstantTableImpl, ID3DXConstantTable_iface);
637 static inline int is_vertex_shader(DWORD version)
639 return (version & 0xFFFF0000) == 0xFFFE0000;
642 static DWORD calc_bytes(D3DXCONSTANT_DESC *desc)
644 if (desc->RegisterSet != D3DXRS_FLOAT4 && desc->RegisterSet != D3DXRS_SAMPLER)
645 FIXME("Don't know how to calculate Bytes for constants of type %d\n",
648 return 4 * desc->Elements * desc->Rows * desc->Columns;
651 /*** IUnknown methods ***/
652 static HRESULT WINAPI ID3DXConstantTableImpl_QueryInterface(ID3DXConstantTable* iface, REFIID riid, void** ppvObject)
654 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
656 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
658 if (IsEqualGUID(riid, &IID_IUnknown) ||
659 IsEqualGUID(riid, &IID_ID3DXBuffer) ||
660 IsEqualGUID(riid, &IID_ID3DXConstantTable))
662 ID3DXConstantTable_AddRef(iface);
667 WARN("Interface %s not found.\n", debugstr_guid(riid));
669 return E_NOINTERFACE;
672 static ULONG WINAPI ID3DXConstantTableImpl_AddRef(ID3DXConstantTable* iface)
674 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
676 TRACE("(%p)->(): AddRef from %d\n", This, This->ref);
678 return InterlockedIncrement(&This->ref);
681 static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable* iface)
683 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
684 ULONG ref = InterlockedDecrement(&This->ref);
686 TRACE("(%p)->(): Release from %d\n", This, ref + 1);
690 HeapFree(GetProcessHeap(), 0, This->constants);
691 HeapFree(GetProcessHeap(), 0, This->ctab);
692 HeapFree(GetProcessHeap(), 0, This);
698 /*** ID3DXBuffer methods ***/
699 static LPVOID WINAPI ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable* iface)
701 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
703 TRACE("(%p)->()\n", This);
708 static DWORD WINAPI ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable* iface)
710 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
712 TRACE("(%p)->()\n", This);
717 /*** ID3DXConstantTable methods ***/
718 static HRESULT WINAPI ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable* iface, D3DXCONSTANTTABLE_DESC *desc)
720 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
722 TRACE("(%p)->(%p)\n", This, desc);
725 return D3DERR_INVALIDCALL;
727 memcpy(desc, &This->desc, sizeof(This->desc));
732 static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable* iface, D3DXHANDLE constant,
733 D3DXCONSTANT_DESC *desc, UINT *count)
735 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
736 ctab_constant *constant_info;
738 TRACE("(%p)->(%p, %p, %p)\n", This, constant, desc, count);
741 return D3DERR_INVALIDCALL;
743 /* Applications can pass the name of the constant in place of the handle */
744 if (!((UINT_PTR)constant >> 16))
745 constant_info = &This->constants[(UINT_PTR)constant - 1];
748 D3DXHANDLE c = ID3DXConstantTable_GetConstantByName(iface, NULL, constant);
750 return D3DERR_INVALIDCALL;
752 constant_info = &This->constants[(UINT_PTR)c - 1];
756 *desc = constant_info->desc;
763 static UINT WINAPI ID3DXConstantTableImpl_GetSamplerIndex(ID3DXConstantTable *iface, D3DXHANDLE constant)
765 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
766 D3DXCONSTANT_DESC desc;
770 TRACE("(%p)->(%p)\n", This, constant);
772 res = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &count);
776 if (desc.RegisterSet != D3DXRS_SAMPLER)
779 return desc.RegisterIndex;
782 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable* iface, D3DXHANDLE constant, UINT index)
784 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
786 TRACE("(%p)->(%p, %d)\n", This, constant, index);
790 FIXME("Only top level constants supported\n");
794 if (index >= This->desc.Constants)
797 return (D3DXHANDLE)(DWORD_PTR)(index + 1);
800 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable* iface, D3DXHANDLE constant, LPCSTR name)
802 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
805 TRACE("(%p)->(%p, %s)\n", This, constant, name);
812 FIXME("Only top level constants supported\n");
816 for (i = 0; i < This->desc.Constants; i++)
817 if (!strcmp(This->constants[i].desc.Name, name))
818 return (D3DXHANDLE)(DWORD_PTR)(i + 1);
823 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable* iface, D3DXHANDLE constant, UINT index)
825 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
827 FIXME("(%p)->(%p, %d): stub\n", This, constant, index);
832 static HRESULT set_float_array(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device, D3DXHANDLE constant, const void *data,
833 UINT count, D3DXPARAMETER_TYPE type)
835 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
837 D3DXCONSTANT_DESC desc;
839 UINT i, desc_count = 1;
840 float row[4] = {0.0f, 0.0f, 0.0f, 0.0f};
842 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
845 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
846 return D3DERR_INVALIDCALL;
849 switch (desc.RegisterSet)
852 for (i = 0; i < count && i < desc.RegisterCount; i++)
854 /* We need the for loop since each IDirect3DDevice9_Set*ShaderConstantF expects a float4 */
858 row[0] = ((float *)data)[i];
861 row[0] = (float)((int *)data)[i];
864 FIXME("Unhandled type passed to set_float_array\n");
865 return D3DERR_INVALIDCALL;
867 if (is_vertex_shader(This->desc.Version))
868 IDirect3DDevice9_SetVertexShaderConstantF(device, desc.RegisterIndex + i, row, 1);
870 IDirect3DDevice9_SetPixelShaderConstantF(device, desc.RegisterIndex + i, row, 1);
874 FIXME("Handle other register sets\n");
881 static HRESULT WINAPI ID3DXConstantTableImpl_SetDefaults(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device)
883 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
885 FIXME("(%p)->(%p): stub\n", This, device);
890 static HRESULT WINAPI ID3DXConstantTableImpl_SetValue(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
891 D3DXHANDLE constant, LPCVOID data, UINT bytes)
893 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
895 FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, data, bytes);
900 static HRESULT WINAPI ID3DXConstantTableImpl_SetBool(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
901 D3DXHANDLE constant, BOOL b)
903 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
905 FIXME("(%p)->(%p, %p, %d): stub\n", This, device, constant, b);
910 static HRESULT WINAPI ID3DXConstantTableImpl_SetBoolArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
911 D3DXHANDLE constant, CONST BOOL* b, UINT count)
913 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
915 FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, b, count);
920 static HRESULT WINAPI ID3DXConstantTableImpl_SetInt(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device, D3DXHANDLE constant, INT n)
922 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
924 TRACE("(%p)->(%p, %p, %d)\n", This, device, constant, n);
926 return ID3DXConstantTable_SetIntArray(iface, device, constant, &n, 1);
929 static HRESULT WINAPI ID3DXConstantTableImpl_SetIntArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
930 D3DXHANDLE constant, CONST INT* n, UINT count)
932 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
934 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, n, count);
936 return set_float_array(iface, device, constant, n, count, D3DXPT_INT);
939 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloat(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
940 D3DXHANDLE constant, FLOAT f)
942 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
944 TRACE("(%p)->(%p, %p, %f)\n", This, device, constant, f);
946 return ID3DXConstantTable_SetFloatArray(iface, device, constant, &f, 1);
949 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloatArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
950 D3DXHANDLE constant, CONST FLOAT *f, UINT count)
952 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
954 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, f, count);
956 return set_float_array(iface, device, constant, f, count, D3DXPT_FLOAT);
959 static HRESULT WINAPI ID3DXConstantTableImpl_SetVector(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
960 D3DXHANDLE constant, CONST D3DXVECTOR4 *vector)
962 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
964 TRACE("(%p)->(%p, %p, %p)\n", This, device, constant, vector);
966 return ID3DXConstantTable_SetVectorArray(iface, device, constant, vector, 1);
969 static HRESULT WINAPI ID3DXConstantTableImpl_SetVectorArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
970 D3DXHANDLE constant, CONST D3DXVECTOR4 *vector, UINT count)
972 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
974 D3DXCONSTANT_DESC desc;
978 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, vector, count);
980 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
983 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
984 return D3DERR_INVALIDCALL;
987 switch (desc.RegisterSet)
990 if (is_vertex_shader(This->desc.Version))
991 IDirect3DDevice9_SetVertexShaderConstantF(device, desc.RegisterIndex, (float *)vector,
992 min(desc.RegisterCount, count));
994 IDirect3DDevice9_SetPixelShaderConstantF(device, desc.RegisterIndex, (float *)vector,
995 min(desc.RegisterCount, count));
998 FIXME("Handle other register sets\n");
1005 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrix(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
1006 D3DXHANDLE constant, CONST D3DXMATRIX *matrix)
1008 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1010 TRACE("(%p)->(%p, %p, %p)\n", This, device, constant, matrix);
1012 return ID3DXConstantTable_SetMatrixArray(iface, device, constant, matrix, 1);
1015 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
1016 D3DXHANDLE constant, CONST D3DXMATRIX *matrix, UINT count)
1018 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1020 D3DXCONSTANT_DESC desc;
1022 UINT i, desc_count = 1;
1025 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, matrix, count);
1027 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
1030 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
1031 return D3DERR_INVALIDCALL;
1034 switch (desc.RegisterSet)
1037 /* i * 4 + 3 is the last register we set. The conditional makes sure that we don't access
1038 registers we're not supposed to */
1039 for (i = 0; i < count && i * 4 + 3 < desc.RegisterCount; i++)
1041 if (desc.Class == D3DXPC_MATRIX_ROWS)
1044 D3DXMatrixTranspose(&temp, &matrix[i]);
1046 if (is_vertex_shader(This->desc.Version))
1047 IDirect3DDevice9_SetVertexShaderConstantF(device, desc.RegisterIndex + i * 4, &temp.u.s._11, 4);
1049 IDirect3DDevice9_SetPixelShaderConstantF(device, desc.RegisterIndex + i * 4, &temp.u.s._11, 4);
1053 FIXME("Handle other register sets\n");
1060 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixPointerArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
1061 D3DXHANDLE constant, CONST D3DXMATRIX** matrix, UINT count)
1063 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1065 FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
1070 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTranspose(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
1071 D3DXHANDLE constant, CONST D3DXMATRIX* matrix)
1073 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1075 FIXME("(%p)->(%p, %p, %p): stub\n", This, device, constant, matrix);
1080 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposeArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
1081 D3DXHANDLE constant, CONST D3DXMATRIX* matrix, UINT count)
1083 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1085 FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
1090 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposePointerArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
1091 D3DXHANDLE constant, CONST D3DXMATRIX** matrix, UINT count)
1093 ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1095 FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
1100 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl =
1102 /*** IUnknown methods ***/
1103 ID3DXConstantTableImpl_QueryInterface,
1104 ID3DXConstantTableImpl_AddRef,
1105 ID3DXConstantTableImpl_Release,
1106 /*** ID3DXBuffer methods ***/
1107 ID3DXConstantTableImpl_GetBufferPointer,
1108 ID3DXConstantTableImpl_GetBufferSize,
1109 /*** ID3DXConstantTable methods ***/
1110 ID3DXConstantTableImpl_GetDesc,
1111 ID3DXConstantTableImpl_GetConstantDesc,
1112 ID3DXConstantTableImpl_GetSamplerIndex,
1113 ID3DXConstantTableImpl_GetConstant,
1114 ID3DXConstantTableImpl_GetConstantByName,
1115 ID3DXConstantTableImpl_GetConstantElement,
1116 ID3DXConstantTableImpl_SetDefaults,
1117 ID3DXConstantTableImpl_SetValue,
1118 ID3DXConstantTableImpl_SetBool,
1119 ID3DXConstantTableImpl_SetBoolArray,
1120 ID3DXConstantTableImpl_SetInt,
1121 ID3DXConstantTableImpl_SetIntArray,
1122 ID3DXConstantTableImpl_SetFloat,
1123 ID3DXConstantTableImpl_SetFloatArray,
1124 ID3DXConstantTableImpl_SetVector,
1125 ID3DXConstantTableImpl_SetVectorArray,
1126 ID3DXConstantTableImpl_SetMatrix,
1127 ID3DXConstantTableImpl_SetMatrixArray,
1128 ID3DXConstantTableImpl_SetMatrixPointerArray,
1129 ID3DXConstantTableImpl_SetMatrixTranspose,
1130 ID3DXConstantTableImpl_SetMatrixTransposeArray,
1131 ID3DXConstantTableImpl_SetMatrixTransposePointerArray
1134 static HRESULT parse_ctab_constant_type(const D3DXSHADER_TYPEINFO *type, ctab_constant *constant)
1136 constant->desc.Class = type->Class;
1137 constant->desc.Type = type->Type;
1138 constant->desc.Rows = type->Rows;
1139 constant->desc.Columns = type->Columns;
1140 constant->desc.Elements = type->Elements;
1141 constant->desc.StructMembers = type->StructMembers;
1142 constant->desc.Bytes = calc_bytes(&constant->desc);
1144 TRACE("class = %d, type = %d, rows = %d, columns = %d, elements = %d, struct_members = %d\n",
1145 constant->desc.Class, constant->desc.Type, constant->desc.Elements,
1146 constant->desc.Rows, constant->desc.Columns, constant->desc.StructMembers);
1148 if ((constant->desc.Class == D3DXPC_STRUCT) && constant->desc.StructMembers)
1150 FIXME("Struct not supported yet\n");
1157 HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code,
1159 LPD3DXCONSTANTTABLE* constant_table)
1161 ID3DXConstantTableImpl* object = NULL;
1165 const D3DXSHADER_CONSTANTTABLE* ctab_header;
1166 D3DXSHADER_CONSTANTINFO* constant_info;
1169 TRACE("(%p, %x, %p)\n", byte_code, flags, constant_table);
1171 if (!byte_code || !constant_table)
1172 return D3DERR_INVALIDCALL;
1174 hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), &data, &size);
1176 return D3DXERR_INVALIDDATA;
1178 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1181 ERR("Out of memory\n");
1182 return E_OUTOFMEMORY;
1185 object->ID3DXConstantTable_iface.lpVtbl = &ID3DXConstantTable_Vtbl;
1188 if (size < sizeof(D3DXSHADER_CONSTANTTABLE))
1190 hr = D3DXERR_INVALIDDATA;
1194 object->ctab = HeapAlloc(GetProcessHeap(), 0, size);
1197 ERR("Out of memory\n");
1201 object->size = size;
1202 memcpy(object->ctab, data, object->size);
1204 ctab_header = (const D3DXSHADER_CONSTANTTABLE*)data;
1205 if (ctab_header->Size != sizeof(D3DXSHADER_CONSTANTTABLE))
1207 hr = D3DXERR_INVALIDDATA;
1210 object->desc.Creator = ctab_header->Creator ? object->ctab + ctab_header->Creator : NULL;
1211 object->desc.Version = ctab_header->Version;
1212 object->desc.Constants = ctab_header->Constants;
1213 if (object->desc.Creator)
1214 TRACE("Creator = %s\n", object->desc.Creator);
1215 TRACE("Version = %x\n", object->desc.Version);
1216 TRACE("Constants = %d\n", ctab_header->Constants);
1217 if (ctab_header->Target)
1218 TRACE("Target = %s\n", object->ctab + ctab_header->Target);
1220 if (object->desc.Constants > 65535)
1222 FIXME("Too many constants (%u)\n", object->desc.Constants);
1227 object->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1228 sizeof(*object->constants) * object->desc.Constants);
1229 if (!object->constants)
1231 ERR("Out of memory\n");
1236 constant_info = (LPD3DXSHADER_CONSTANTINFO)(object->ctab + ctab_header->ConstantInfo);
1237 for (i = 0; i < ctab_header->Constants; i++)
1239 TRACE("name = %s\n", object->ctab + constant_info[i].Name);
1240 object->constants[i].desc.Name = object->ctab + constant_info[i].Name;
1241 object->constants[i].desc.RegisterSet = constant_info[i].RegisterSet;
1242 object->constants[i].desc.RegisterIndex = constant_info[i].RegisterIndex;
1243 object->constants[i].desc.RegisterCount = constant_info[i].RegisterCount;
1244 object->constants[i].desc.DefaultValue = object->ctab + constant_info[i].DefaultValue;
1246 hr = parse_ctab_constant_type((LPD3DXSHADER_TYPEINFO)(object->ctab + constant_info[i].TypeInfo),
1247 &object->constants[i]);
1252 *constant_table = &object->ID3DXConstantTable_iface;
1258 HeapFree(GetProcessHeap(), 0, object->constants);
1259 HeapFree(GetProcessHeap(), 0, object->ctab);
1260 HeapFree(GetProcessHeap(), 0, object);
1265 HRESULT WINAPI D3DXGetShaderConstantTable(CONST DWORD* byte_code,
1266 LPD3DXCONSTANTTABLE* constant_table)
1268 TRACE("(%p, %p): Forwarded to D3DXGetShaderConstantTableEx\n", byte_code, constant_table);
1270 return D3DXGetShaderConstantTableEx(byte_code, 0, constant_table);
1273 HRESULT WINAPI D3DXGetShaderSamplers(CONST DWORD *byte_code, LPCSTR *samplers, UINT *count)
1276 UINT i, sampler_count = 0;
1279 const D3DXSHADER_CONSTANTTABLE *ctab_header;
1280 const D3DXSHADER_CONSTANTINFO *constant_info;
1282 TRACE("byte_code %p, samplers %p, count %p\n", byte_code, samplers, count);
1284 if (count) *count = 0;
1286 hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), (LPCVOID *)&data, &size);
1287 if (hr != D3D_OK) return D3D_OK;
1289 if (size < sizeof(D3DXSHADER_CONSTANTTABLE)) return D3D_OK;
1291 ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data;
1292 if (ctab_header->Size != sizeof(*ctab_header)) return D3D_OK;
1294 constant_info = (D3DXSHADER_CONSTANTINFO *)(data + ctab_header->ConstantInfo);
1295 for (i = 0; i < ctab_header->Constants; i++)
1297 const D3DXSHADER_TYPEINFO *type;
1299 TRACE("name = %s\n", data + constant_info[i].Name);
1301 type = (D3DXSHADER_TYPEINFO *)(data + constant_info[i].TypeInfo);
1303 if (type->Type == D3DXPT_SAMPLER
1304 || type->Type == D3DXPT_SAMPLER1D
1305 || type->Type == D3DXPT_SAMPLER2D
1306 || type->Type == D3DXPT_SAMPLER3D
1307 || type->Type == D3DXPT_SAMPLERCUBE)
1309 if (samplers) samplers[sampler_count] = data + constant_info[i].Name;
1315 TRACE("Found %u samplers\n", sampler_count);
1317 if (count) *count = sampler_count;