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(LPCSTR data
,
190 CONST D3DXMACRO
* defines
,
191 LPD3DXINCLUDE include
,
193 LPD3DXBUFFER
* shader
,
194 LPD3DXBUFFER
* error_messages
)
196 /* Forward to d3dcompiler: the parameter types aren't really different,
197 the actual data types are equivalent */
198 HRESULT hr
= D3DAssemble(data
, data_len
, NULL
, (D3D_SHADER_MACRO
*)defines
,
199 (ID3DInclude
*)include
, flags
, (ID3DBlob
**)shader
,
200 (ID3DBlob
**)error_messages
);
202 if(hr
== E_FAIL
) hr
= D3DXERR_INVALIDDATA
;
206 /* D3DXInclude private implementation, used to implement
207 D3DXAssembleShaderFromFile from D3DXAssembleShader */
208 /* To be able to correctly resolve include search paths we have to store
209 the pathname of each include file. We store the pathname pointer right
210 before the file data. */
211 static HRESULT WINAPI
d3dincludefromfile_open(ID3DXInclude
*iface
,
212 D3DXINCLUDE_TYPE include_type
,
213 LPCSTR filename
, LPCVOID parent_data
,
214 LPCVOID
*data
, UINT
*bytes
) {
215 const char *p
, *parent_name
= "";
216 char *pathname
= NULL
;
217 char **buffer
= NULL
;
221 if(parent_data
!= NULL
)
222 parent_name
= *((const char **)parent_data
- 1);
224 TRACE("Looking up for include file %s, parent %s\n", debugstr_a(filename
), debugstr_a(parent_name
));
226 if ((p
= strrchr(parent_name
, '\\')) || (p
= strrchr(parent_name
, '/'))) p
++;
227 else p
= parent_name
;
228 pathname
= HeapAlloc(GetProcessHeap(), 0, (p
- parent_name
) + strlen(filename
) + 1);
230 return HRESULT_FROM_WIN32(GetLastError());
232 memcpy(pathname
, parent_name
, p
- parent_name
);
233 strcpy(pathname
+ (p
- parent_name
), filename
);
235 file
= CreateFileA(pathname
, GENERIC_READ
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
236 if(file
== INVALID_HANDLE_VALUE
)
239 TRACE("Include file found at pathname = %s\n", debugstr_a(pathname
));
241 size
= GetFileSize(file
, NULL
);
242 if(size
== INVALID_FILE_SIZE
)
245 buffer
= HeapAlloc(GetProcessHeap(), 0, size
+ sizeof(char *));
249 if(!ReadFile(file
, buffer
+ 1, size
, bytes
, NULL
))
259 HeapFree(GetProcessHeap(), 0, pathname
);
260 HeapFree(GetProcessHeap(), 0, buffer
);
261 return HRESULT_FROM_WIN32(GetLastError());
264 static HRESULT WINAPI
d3dincludefromfile_close(ID3DXInclude
*iface
, LPCVOID data
) {
265 HeapFree(GetProcessHeap(), 0, *((char **)data
- 1));
266 HeapFree(GetProcessHeap(), 0, (char **)data
- 1);
270 static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl
= {
271 d3dincludefromfile_open
,
272 d3dincludefromfile_close
275 struct D3DXIncludeImpl
{
276 ID3DXInclude ID3DXInclude_iface
;
279 HRESULT WINAPI
D3DXAssembleShaderFromFileA(LPCSTR filename
,
280 CONST D3DXMACRO
* defines
,
281 LPD3DXINCLUDE include
,
283 LPD3DXBUFFER
* shader
,
284 LPD3DXBUFFER
* error_messages
)
286 LPWSTR filename_w
= NULL
;
290 if (!filename
) return D3DXERR_INVALIDDATA
;
292 len
= MultiByteToWideChar(CP_ACP
, 0, filename
, -1, NULL
, 0);
293 filename_w
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
294 if (!filename_w
) return E_OUTOFMEMORY
;
295 MultiByteToWideChar(CP_ACP
, 0, filename
, -1, filename_w
, len
);
297 ret
= D3DXAssembleShaderFromFileW(filename_w
, defines
, include
, flags
, shader
, error_messages
);
299 HeapFree(GetProcessHeap(), 0, filename_w
);
303 HRESULT WINAPI
D3DXAssembleShaderFromFileW(LPCWSTR filename
,
304 CONST D3DXMACRO
* defines
,
305 LPD3DXINCLUDE include
,
307 LPD3DXBUFFER
* shader
,
308 LPD3DXBUFFER
* error_messages
)
313 struct D3DXIncludeImpl includefromfile
;
315 if(FAILED(map_view_of_file(filename
, &buffer
, &len
)))
316 return D3DXERR_INVALIDDATA
;
320 includefromfile
.ID3DXInclude_iface
.lpVtbl
= &D3DXInclude_Vtbl
;
321 include
= &includefromfile
.ID3DXInclude_iface
;
324 hr
= D3DXAssembleShader(buffer
, len
, defines
, include
, flags
,
325 shader
, error_messages
);
327 UnmapViewOfFile(buffer
);
331 HRESULT WINAPI
D3DXAssembleShaderFromResourceA(HMODULE module
,
333 CONST D3DXMACRO
* defines
,
334 LPD3DXINCLUDE include
,
336 LPD3DXBUFFER
* shader
,
337 LPD3DXBUFFER
* error_messages
)
343 if (!(res
= FindResourceA(module
, resource
, (LPCSTR
)RT_RCDATA
)))
344 return D3DXERR_INVALIDDATA
;
345 if (FAILED(load_resource_into_memory(module
, res
, (LPVOID
*)&buffer
, &len
)))
346 return D3DXERR_INVALIDDATA
;
347 return D3DXAssembleShader(buffer
, len
, defines
, include
, flags
,
348 shader
, error_messages
);
351 HRESULT WINAPI
D3DXAssembleShaderFromResourceW(HMODULE module
,
353 CONST D3DXMACRO
* defines
,
354 LPD3DXINCLUDE include
,
356 LPD3DXBUFFER
* shader
,
357 LPD3DXBUFFER
* error_messages
)
363 if (!(res
= FindResourceW(module
, resource
, (LPCWSTR
)RT_RCDATA
)))
364 return D3DXERR_INVALIDDATA
;
365 if (FAILED(load_resource_into_memory(module
, res
, (LPVOID
*)&buffer
, &len
)))
366 return D3DXERR_INVALIDDATA
;
367 return D3DXAssembleShader(buffer
, len
, defines
, include
, flags
,
368 shader
, error_messages
);
371 HRESULT WINAPI
D3DXCompileShader(LPCSTR pSrcData
,
373 CONST D3DXMACRO
* pDefines
,
374 LPD3DXINCLUDE pInclude
,
375 LPCSTR pFunctionName
,
378 LPD3DXBUFFER
* ppShader
,
379 LPD3DXBUFFER
* ppErrorMsgs
,
380 LPD3DXCONSTANTTABLE
* ppConstantTable
)
382 HRESULT hr
= D3DCompile(pSrcData
, srcDataLen
, NULL
,
383 (D3D_SHADER_MACRO
*)pDefines
, (ID3DInclude
*)pInclude
,
384 pFunctionName
, pProfile
, Flags
, 0,
385 (ID3DBlob
**)ppShader
, (ID3DBlob
**)ppErrorMsgs
);
387 if(SUCCEEDED(hr
) && ppConstantTable
)
388 return D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*ppShader
),
393 HRESULT WINAPI
D3DXCompileShaderFromFileA(LPCSTR filename
,
394 CONST D3DXMACRO
* defines
,
395 LPD3DXINCLUDE include
,
399 LPD3DXBUFFER
* shader
,
400 LPD3DXBUFFER
* error_messages
,
401 LPD3DXCONSTANTTABLE
* constant_table
)
403 LPWSTR filename_w
= NULL
;
407 if (!filename
) return D3DXERR_INVALIDDATA
;
409 len
= MultiByteToWideChar(CP_ACP
, 0, filename
, -1, NULL
, 0);
410 filename_w
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
411 if (!filename_w
) return E_OUTOFMEMORY
;
412 MultiByteToWideChar(CP_ACP
, 0, filename
, -1, filename_w
, len
);
414 ret
= D3DXCompileShaderFromFileW(filename_w
, defines
, include
,
415 entrypoint
, profile
, flags
,
416 shader
, error_messages
, constant_table
);
418 HeapFree(GetProcessHeap(), 0, filename_w
);
422 HRESULT WINAPI
D3DXCompileShaderFromFileW(LPCWSTR filename
,
423 CONST D3DXMACRO
* defines
,
424 LPD3DXINCLUDE include
,
428 LPD3DXBUFFER
* shader
,
429 LPD3DXBUFFER
* error_messages
,
430 LPD3DXCONSTANTTABLE
* constant_table
)
433 DWORD len
, filename_len
;
435 struct D3DXIncludeImpl includefromfile
;
438 if (FAILED(map_view_of_file(filename
, &buffer
, &len
)))
439 return D3DXERR_INVALIDDATA
;
443 includefromfile
.ID3DXInclude_iface
.lpVtbl
= &D3DXInclude_Vtbl
;
444 include
= &includefromfile
.ID3DXInclude_iface
;
447 filename_len
= WideCharToMultiByte(CP_ACP
, 0, filename
, -1, NULL
, 0, NULL
, NULL
);
448 filename_a
= HeapAlloc(GetProcessHeap(), 0, filename_len
* sizeof(char));
451 UnmapViewOfFile(buffer
);
452 return E_OUTOFMEMORY
;
454 WideCharToMultiByte(CP_ACP
, 0, filename
, -1, filename_a
, filename_len
, NULL
, NULL
);
456 hr
= D3DCompile(buffer
, len
, filename_a
, (const D3D_SHADER_MACRO
*)defines
,
457 (ID3DInclude
*)include
, entrypoint
, profile
, flags
, 0,
458 (ID3DBlob
**)shader
, (ID3DBlob
**)error_messages
);
460 if (SUCCEEDED(hr
) && constant_table
)
461 hr
= D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader
),
464 HeapFree(GetProcessHeap(), 0, filename_a
);
465 UnmapViewOfFile(buffer
);
469 HRESULT WINAPI
D3DXCompileShaderFromResourceA(HMODULE module
,
471 CONST D3DXMACRO
* defines
,
472 LPD3DXINCLUDE include
,
476 LPD3DXBUFFER
* shader
,
477 LPD3DXBUFFER
* error_messages
,
478 LPD3DXCONSTANTTABLE
* constant_table
)
484 if (!(res
= FindResourceA(module
, resource
, (LPCSTR
)RT_RCDATA
)))
485 return D3DXERR_INVALIDDATA
;
486 if (FAILED(load_resource_into_memory(module
, res
, (LPVOID
*)&buffer
, &len
)))
487 return D3DXERR_INVALIDDATA
;
488 return D3DXCompileShader(buffer
, len
, defines
, include
, entrypoint
, profile
,
489 flags
, shader
, error_messages
, constant_table
);
492 HRESULT WINAPI
D3DXCompileShaderFromResourceW(HMODULE module
,
494 CONST D3DXMACRO
* defines
,
495 LPD3DXINCLUDE include
,
499 LPD3DXBUFFER
* shader
,
500 LPD3DXBUFFER
* error_messages
,
501 LPD3DXCONSTANTTABLE
* constant_table
)
507 if (!(res
= FindResourceW(module
, resource
, (LPCWSTR
)RT_RCDATA
)))
508 return D3DXERR_INVALIDDATA
;
509 if (FAILED(load_resource_into_memory(module
, res
, (LPVOID
*)&buffer
, &len
)))
510 return D3DXERR_INVALIDDATA
;
511 return D3DXCompileShader(buffer
, len
, defines
, include
, entrypoint
, profile
,
512 flags
, shader
, error_messages
, constant_table
);
515 HRESULT WINAPI
D3DXPreprocessShader(LPCSTR data
,
517 CONST D3DXMACRO
* defines
,
518 LPD3DXINCLUDE include
,
519 LPD3DXBUFFER
* shader
,
520 LPD3DXBUFFER
* error_messages
)
522 TRACE("Forward to D3DPreprocess\n");
523 return D3DPreprocess(data
, data_len
, NULL
,
524 (const D3D_SHADER_MACRO
*)defines
, (ID3DInclude
*)include
,
525 (ID3DBlob
**)shader
, (ID3DBlob
**)error_messages
);
528 HRESULT WINAPI
D3DXPreprocessShaderFromFileA(LPCSTR filename
,
529 CONST D3DXMACRO
* defines
,
530 LPD3DXINCLUDE include
,
531 LPD3DXBUFFER
* shader
,
532 LPD3DXBUFFER
* error_messages
)
534 WCHAR
*filename_w
= NULL
;
538 if (!filename
) return D3DXERR_INVALIDDATA
;
540 len
= MultiByteToWideChar(CP_ACP
, 0, filename
, -1, NULL
, 0);
541 filename_w
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
542 if (!filename_w
) return E_OUTOFMEMORY
;
543 MultiByteToWideChar(CP_ACP
, 0, filename
, -1, filename_w
, len
);
545 ret
= D3DXPreprocessShaderFromFileW(filename_w
, defines
, include
, shader
, error_messages
);
547 HeapFree(GetProcessHeap(), 0, filename_w
);
551 HRESULT WINAPI
D3DXPreprocessShaderFromFileW(LPCWSTR filename
,
552 CONST D3DXMACRO
* defines
,
553 LPD3DXINCLUDE include
,
554 LPD3DXBUFFER
* shader
,
555 LPD3DXBUFFER
* error_messages
)
560 struct D3DXIncludeImpl includefromfile
;
562 if (FAILED(map_view_of_file(filename
, &buffer
, &len
)))
563 return D3DXERR_INVALIDDATA
;
567 includefromfile
.ID3DXInclude_iface
.lpVtbl
= &D3DXInclude_Vtbl
;
568 include
= &includefromfile
.ID3DXInclude_iface
;
571 hr
= D3DPreprocess(buffer
, len
, NULL
,
572 (const D3D_SHADER_MACRO
*)defines
,
573 (ID3DInclude
*) include
,
574 (ID3DBlob
**)shader
, (ID3DBlob
**)error_messages
);
576 UnmapViewOfFile(buffer
);
580 HRESULT WINAPI
D3DXPreprocessShaderFromResourceA(HMODULE module
,
582 CONST D3DXMACRO
* defines
,
583 LPD3DXINCLUDE include
,
584 LPD3DXBUFFER
* shader
,
585 LPD3DXBUFFER
* error_messages
)
591 if (!(res
= FindResourceA(module
, resource
, (LPCSTR
)RT_RCDATA
)))
592 return D3DXERR_INVALIDDATA
;
593 if (FAILED(load_resource_into_memory(module
, res
, (LPVOID
*)&buffer
, &len
)))
594 return D3DXERR_INVALIDDATA
;
595 return D3DXPreprocessShader(buffer
, len
, defines
, include
,
596 shader
, error_messages
);
599 HRESULT WINAPI
D3DXPreprocessShaderFromResourceW(HMODULE module
,
601 CONST D3DXMACRO
* defines
,
602 LPD3DXINCLUDE include
,
603 LPD3DXBUFFER
* shader
,
604 LPD3DXBUFFER
* error_messages
)
610 if (!(res
= FindResourceW(module
, resource
, (const WCHAR
*)RT_RCDATA
)))
611 return D3DXERR_INVALIDDATA
;
612 if (FAILED(load_resource_into_memory(module
, res
, (void **)&buffer
, &len
)))
613 return D3DXERR_INVALIDDATA
;
614 return D3DXPreprocessShader(buffer
, len
, defines
, include
,
615 shader
, error_messages
);
619 struct ctab_constant
{
620 D3DXCONSTANT_DESC desc
;
621 struct ctab_constant
*constants
;
624 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl
;
626 struct ID3DXConstantTableImpl
{
627 ID3DXConstantTable ID3DXConstantTable_iface
;
631 D3DXCONSTANTTABLE_DESC desc
;
632 struct ctab_constant
*constants
;
635 static void free_constant(struct ctab_constant
*constant
)
637 if (constant
->constants
)
639 UINT i
, count
= constant
->desc
.Elements
> 1 ? constant
->desc
.Elements
: constant
->desc
.StructMembers
;
641 for (i
= 0; i
< count
; ++i
)
643 free_constant(&constant
->constants
[i
]);
645 HeapFree(GetProcessHeap(), 0, constant
->constants
);
649 static void free_constant_table(struct ID3DXConstantTableImpl
*table
)
651 if (table
->constants
)
655 for (i
= 0; i
< table
->desc
.Constants
; ++i
)
657 free_constant(&table
->constants
[i
]);
659 HeapFree(GetProcessHeap(), 0, table
->constants
);
661 HeapFree(GetProcessHeap(), 0, table
->ctab
);
664 static inline struct ID3DXConstantTableImpl
*impl_from_ID3DXConstantTable(ID3DXConstantTable
*iface
)
666 return CONTAINING_RECORD(iface
, struct ID3DXConstantTableImpl
, ID3DXConstantTable_iface
);
669 static inline int is_vertex_shader(DWORD version
)
671 return (version
& 0xFFFF0000) == 0xFFFE0000;
674 static inline struct ctab_constant
*constant_from_handle(D3DXHANDLE handle
)
676 return (struct ctab_constant
*)handle
;
679 static inline D3DXHANDLE
handle_from_constant(struct ctab_constant
*constant
)
681 return (D3DXHANDLE
)constant
;
684 static struct ctab_constant
*get_constant_by_name(struct ID3DXConstantTableImpl
*, struct ctab_constant
*, LPCSTR
);
686 static struct ctab_constant
*get_constant_element_by_name(struct ctab_constant
*constant
, LPCSTR name
)
691 TRACE("constant %p, name %s\n", constant
, debugstr_a(name
));
693 if (!name
|| !*name
) return NULL
;
695 element
= atoi(name
);
696 part
= strchr(name
, ']') + 1;
698 if (constant
->desc
.Elements
> element
)
700 struct ctab_constant
*c
= constant
->constants
? &constant
->constants
[element
] : constant
;
705 return get_constant_by_name(NULL
, c
, part
);
708 return get_constant_element_by_name(c
, part
);
711 TRACE("Returning parameter %p\n", c
);
715 FIXME("Unhandled case \"%c\"\n", *--part
);
720 TRACE("Constant not found\n");
724 static struct ctab_constant
*get_constant_by_name(struct ID3DXConstantTableImpl
*table
,
725 struct ctab_constant
*constant
, LPCSTR name
)
727 UINT i
, count
, length
;
728 struct ctab_constant
*handles
;
731 TRACE("table %p, constant %p, name %s\n", table
, constant
, debugstr_a(name
));
733 if (!name
|| !*name
) return NULL
;
737 count
= table
->desc
.Constants
;
738 handles
= table
->constants
;
742 count
= constant
->desc
.StructMembers
;
743 handles
= constant
->constants
;
746 length
= strcspn(name
, "[.");
747 part
= name
+ length
;
749 for (i
= 0; i
< count
; i
++)
751 if (strlen(handles
[i
].desc
.Name
) == length
&& !strncmp(handles
[i
].desc
.Name
, name
, length
))
756 return get_constant_by_name(NULL
, &handles
[i
], part
);
759 return get_constant_element_by_name(&handles
[i
], part
);
762 TRACE("Returning parameter %p\n", &handles
[i
]);
768 TRACE("Constant not found\n");
772 static struct ctab_constant
*is_valid_sub_constant(struct ctab_constant
*parent
, struct ctab_constant
*constant
)
776 /* all variable have at least elements = 1, but no elements */
777 if (!parent
->constants
) return NULL
;
779 if (parent
->desc
.Elements
> 1) count
= parent
->desc
.Elements
;
780 else count
= parent
->desc
.StructMembers
;
782 for (i
= 0; i
< count
; ++i
)
784 if (&parent
->constants
[i
] == constant
)
787 if (is_valid_sub_constant(&parent
->constants
[i
], constant
))
794 static inline struct ctab_constant
*is_valid_constant(struct ID3DXConstantTableImpl
*table
, D3DXHANDLE handle
)
796 struct ctab_constant
*c
= constant_from_handle(handle
);
801 for (i
= 0; i
< table
->desc
.Constants
; ++i
)
803 if (&table
->constants
[i
] == c
)
806 if (is_valid_sub_constant(&table
->constants
[i
], c
))
813 static inline struct ctab_constant
*get_valid_constant(struct ID3DXConstantTableImpl
*table
, D3DXHANDLE handle
)
815 struct ctab_constant
*constant
= is_valid_constant(table
, handle
);
817 if (!constant
) constant
= get_constant_by_name(table
, NULL
, handle
);
822 static inline void set_float_shader_constant(struct ID3DXConstantTableImpl
*table
, IDirect3DDevice9
*device
,
823 UINT register_index
, const FLOAT
*data
, UINT count
)
825 if (is_vertex_shader(table
->desc
.Version
))
826 IDirect3DDevice9_SetVertexShaderConstantF(device
, register_index
, data
, count
);
828 IDirect3DDevice9_SetPixelShaderConstantF(device
, register_index
, data
, count
);
831 /*** IUnknown methods ***/
832 static HRESULT WINAPI
ID3DXConstantTableImpl_QueryInterface(ID3DXConstantTable
*iface
, REFIID riid
, void **out
)
834 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
836 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
837 IsEqualGUID(riid
, &IID_ID3DXBuffer
) ||
838 IsEqualGUID(riid
, &IID_ID3DXConstantTable
))
840 ID3DXConstantTable_AddRef(iface
);
845 WARN("Interface %s not found.\n", debugstr_guid(riid
));
847 return E_NOINTERFACE
;
850 static ULONG WINAPI
ID3DXConstantTableImpl_AddRef(ID3DXConstantTable
*iface
)
852 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
854 TRACE("(%p)->(): AddRef from %d\n", This
, This
->ref
);
856 return InterlockedIncrement(&This
->ref
);
859 static ULONG WINAPI
ID3DXConstantTableImpl_Release(ID3DXConstantTable
*iface
)
861 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
862 ULONG ref
= InterlockedDecrement(&This
->ref
);
864 TRACE("(%p)->(): Release from %d\n", This
, ref
+ 1);
868 free_constant_table(This
);
869 HeapFree(GetProcessHeap(), 0, This
);
875 /*** ID3DXBuffer methods ***/
876 static LPVOID WINAPI
ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable
*iface
)
878 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
880 TRACE("(%p)->()\n", This
);
885 static DWORD WINAPI
ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable
*iface
)
887 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
889 TRACE("(%p)->()\n", This
);
894 /*** ID3DXConstantTable methods ***/
895 static HRESULT WINAPI
ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable
*iface
, D3DXCONSTANTTABLE_DESC
*desc
)
897 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
899 TRACE("(%p)->(%p)\n", This
, desc
);
902 return D3DERR_INVALIDCALL
;
909 static HRESULT WINAPI
ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable
*iface
, D3DXHANDLE constant
,
910 D3DXCONSTANT_DESC
*desc
, UINT
*count
)
912 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
913 struct ctab_constant
*c
= get_valid_constant(This
, constant
);
915 TRACE("(%p)->(%p, %p, %p)\n", This
, constant
, desc
, count
);
919 WARN("Invalid argument specified\n");
920 return D3DERR_INVALIDCALL
;
923 if (desc
) *desc
= c
->desc
;
924 if (count
) *count
= 1;
929 static UINT WINAPI
ID3DXConstantTableImpl_GetSamplerIndex(ID3DXConstantTable
*iface
, D3DXHANDLE constant
)
931 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
932 struct ctab_constant
*c
= get_valid_constant(This
, constant
);
934 TRACE("(%p)->(%p)\n", This
, constant
);
936 if (!c
|| c
->desc
.RegisterSet
!= D3DXRS_SAMPLER
)
938 WARN("Invalid argument specified\n");
942 TRACE("Returning RegisterIndex %u\n", c
->desc
.RegisterIndex
);
943 return c
->desc
.RegisterIndex
;
946 static D3DXHANDLE WINAPI
ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable
*iface
, D3DXHANDLE constant
, UINT index
)
948 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
949 struct ctab_constant
*c
;
951 TRACE("(%p)->(%p, %d)\n", This
, constant
, index
);
955 c
= get_valid_constant(This
, constant
);
956 if (c
&& index
< c
->desc
.StructMembers
)
958 c
= &c
->constants
[index
];
959 TRACE("Returning constant %p\n", c
);
960 return handle_from_constant(c
);
965 if (index
< This
->desc
.Constants
)
967 c
= &This
->constants
[index
];
968 TRACE("Returning constant %p\n", c
);
969 return handle_from_constant(c
);
973 WARN("Index out of range\n");
977 static D3DXHANDLE WINAPI
ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable
*iface
, D3DXHANDLE constant
, LPCSTR name
)
979 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
980 struct ctab_constant
*c
= get_valid_constant(This
, constant
);
982 TRACE("(%p)->(%p, %s)\n", This
, constant
, name
);
984 c
= get_constant_by_name(This
, c
, name
);
985 TRACE("Returning constant %p\n", c
);
987 return handle_from_constant(c
);
990 static D3DXHANDLE WINAPI
ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable
*iface
, D3DXHANDLE constant
, UINT index
)
992 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
993 struct ctab_constant
*c
= get_valid_constant(This
, constant
);
995 TRACE("(%p)->(%p, %d)\n", This
, constant
, index
);
997 if (c
&& index
< c
->desc
.Elements
)
999 if (c
->desc
.Elements
> 1) c
= &c
->constants
[index
];
1000 TRACE("Returning constant %p\n", c
);
1001 return handle_from_constant(c
);
1004 WARN("Invalid argument specified\n");
1008 static HRESULT
set_scalar_array(ID3DXConstantTable
*iface
, IDirect3DDevice9
*device
, D3DXHANDLE constant
, const void *data
,
1009 UINT count
, D3DXPARAMETER_TYPE type
)
1011 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1012 D3DXCONSTANT_DESC desc
;
1014 UINT i
, desc_count
= 1;
1015 float row
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
1017 hr
= ID3DXConstantTable_GetConstantDesc(iface
, constant
, &desc
, &desc_count
);
1020 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr
);
1021 return D3DERR_INVALIDCALL
;
1024 if (desc
.Class
!= D3DXPC_SCALAR
)
1027 switch (desc
.RegisterSet
)
1030 for (i
= 0; i
< min(count
, desc
.RegisterCount
); i
++)
1032 /* We need the for loop since each IDirect3DDevice9_Set*ShaderConstantF expects a float4 */
1036 row
[0] = ((float *)data
)[i
];
1039 row
[0] = (float)((int *)data
)[i
];
1042 row
[0] = ((BOOL
*)data
)[i
] ? 1.0f
: 0.0f
;
1045 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(type
));
1046 return D3DERR_INVALIDCALL
;
1048 set_float_shader_constant(This
, device
, desc
.RegisterIndex
+ i
, row
, 1);
1052 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc
.RegisterSet
));
1059 static HRESULT
set_vector_array(ID3DXConstantTable
*iface
, IDirect3DDevice9
*device
, D3DXHANDLE constant
, const void *data
,
1060 UINT count
, D3DXPARAMETER_TYPE type
)
1062 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1063 D3DXCONSTANT_DESC desc
;
1065 UINT i
, j
, desc_count
= 1;
1066 float vec
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
1068 hr
= ID3DXConstantTable_GetConstantDesc(iface
, constant
, &desc
, &desc_count
);
1071 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr
);
1072 return D3DERR_INVALIDCALL
;
1075 if (desc
.Class
== D3DXPC_MATRIX_ROWS
|| desc
.Class
== D3DXPC_MATRIX_COLUMNS
)
1078 switch (desc
.RegisterSet
)
1081 for (i
= 0; i
< min(count
, desc
.RegisterCount
); i
++)
1086 memcpy(vec
, ((float *)data
) + i
* desc
.Columns
, desc
.Columns
* sizeof(float));
1089 for (j
= 0; j
< desc
.Columns
; j
++)
1090 vec
[j
] = (float)((int *)data
)[i
* desc
.Columns
+ j
];
1093 for (j
= 0; j
< desc
.Columns
; j
++)
1094 vec
[j
] = ((BOOL
*)data
)[i
* desc
.Columns
+ j
] ? 1.0f
: 0.0f
;
1097 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(type
));
1098 return D3DERR_INVALIDCALL
;
1101 set_float_shader_constant(This
, device
, desc
.RegisterIndex
+ i
, vec
, 1);
1105 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc
.RegisterSet
));
1112 static HRESULT
set_float_matrix(FLOAT
*matrix
, const D3DXCONSTANT_DESC
*desc
,
1113 UINT row_offset
, UINT column_offset
, UINT rows
, UINT columns
,
1114 const void *data
, D3DXPARAMETER_TYPE type
, UINT src_columns
)
1121 for (i
= 0; i
< rows
; i
++)
1123 for (j
= 0; j
< columns
; j
++)
1124 matrix
[i
* row_offset
+ j
* column_offset
] = ((FLOAT
*)data
)[i
* src_columns
+ j
];
1128 for (i
= 0; i
< rows
; i
++)
1130 for (j
= 0; j
< columns
; j
++)
1131 matrix
[i
* row_offset
+ j
* column_offset
] = ((INT
*)data
)[i
* src_columns
+ j
];
1135 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(type
));
1136 return D3DERR_INVALIDCALL
;
1142 static HRESULT
set_matrix_array(ID3DXConstantTable
*iface
, IDirect3DDevice9
*device
, D3DXHANDLE constant
, const void *data
,
1143 UINT count
, D3DXPARAMETER_CLASS
class, D3DXPARAMETER_TYPE type
, UINT rows
, UINT columns
)
1145 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1146 struct ctab_constant
*c
= get_valid_constant(This
, constant
);
1147 D3DXCONSTANT_DESC
*desc
;
1148 UINT registers_per_matrix
, num_rows
, num_columns
, i
;
1149 UINT row_offset
= 1, column_offset
= 1;
1150 const DWORD
*data_ptr
;
1151 FLOAT matrix
[16] = {0.0f
, 0.0f
, 0.0f
, 0.0f
,
1152 0.0f
, 0.0f
, 0.0f
, 0.0f
,
1153 0.0f
, 0.0f
, 0.0f
, 0.0f
,
1154 0.0f
, 0.0f
, 0.0f
, 0.0f
};
1158 WARN("Invalid argument specified\n");
1159 return D3DERR_INVALIDCALL
;
1163 if (desc
->Class
== D3DXPC_MATRIX_ROWS
1164 || desc
->Class
== D3DXPC_MATRIX_COLUMNS
1165 || desc
->Class
== D3DXPC_VECTOR
1166 || desc
->Class
== D3DXPC_SCALAR
)
1168 if (desc
->Class
== class) row_offset
= 4;
1169 else column_offset
= 4;
1171 if (class == D3DXPC_MATRIX_ROWS
)
1173 if (desc
->Class
== D3DXPC_VECTOR
) return D3D_OK
;
1175 num_rows
= desc
->Rows
;
1176 num_columns
= desc
->Columns
;
1180 num_rows
= desc
->Columns
;
1181 num_columns
= desc
->Rows
;
1184 registers_per_matrix
= (desc
->Class
== D3DXPC_MATRIX_COLUMNS
) ? desc
->Columns
: desc
->Rows
;
1188 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc
->Class
));
1192 switch (desc
->RegisterSet
)
1196 for (i
= 0; i
< count
; i
++)
1200 if (registers_per_matrix
* (i
+ 1) > desc
->RegisterCount
)
1203 hr
= set_float_matrix(matrix
, desc
, row_offset
, column_offset
, num_rows
, num_columns
, data_ptr
, type
, columns
);
1204 if (FAILED(hr
)) return hr
;
1206 set_float_shader_constant(This
, device
, desc
->RegisterIndex
+ i
* registers_per_matrix
, matrix
, registers_per_matrix
);
1208 data_ptr
+= rows
* columns
;
1212 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc
->RegisterSet
));
1219 static HRESULT
set_matrix_pointer_array(ID3DXConstantTable
*iface
, IDirect3DDevice9
*device
, D3DXHANDLE constant
,
1220 const D3DXMATRIX
**data
, UINT count
, D3DXPARAMETER_CLASS
class)
1222 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1223 D3DXCONSTANT_DESC desc
;
1225 UINT registers_per_matrix
;
1226 UINT i
, desc_count
= 1;
1227 UINT num_rows
, num_columns
;
1228 UINT row_offset
, column_offset
;
1229 FLOAT matrix
[16] = {0.0f
, 0.0f
, 0.0f
, 0.0f
,
1230 0.0f
, 0.0f
, 0.0f
, 0.0f
,
1231 0.0f
, 0.0f
, 0.0f
, 0.0f
,
1232 0.0f
, 0.0f
, 0.0f
, 0.0f
};
1234 hr
= ID3DXConstantTable_GetConstantDesc(iface
, constant
, &desc
, &desc_count
);
1237 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr
);
1238 return D3DERR_INVALIDCALL
;
1241 if (desc
.Class
== D3DXPC_MATRIX_ROWS
|| desc
.Class
== D3DXPC_MATRIX_COLUMNS
)
1243 if (desc
.Class
== class)
1254 if (class == D3DXPC_MATRIX_ROWS
)
1256 num_rows
= desc
.Rows
;
1257 num_columns
= desc
.Columns
;
1261 num_rows
= desc
.Columns
;
1262 num_columns
= desc
.Rows
;
1265 registers_per_matrix
= (desc
.Class
== D3DXPC_MATRIX_ROWS
) ? desc
.Rows
: desc
.Columns
;
1267 else if (desc
.Class
== D3DXPC_SCALAR
)
1269 registers_per_matrix
= 1;
1272 num_rows
= desc
.Rows
;
1273 num_columns
= desc
.Columns
;
1275 else if (desc
.Class
== D3DXPC_VECTOR
)
1277 registers_per_matrix
= 1;
1279 if (class == D3DXPC_MATRIX_ROWS
)
1283 num_rows
= desc
.Rows
;
1284 num_columns
= desc
.Columns
;
1290 num_rows
= desc
.Columns
;
1291 num_columns
= desc
.Rows
;
1296 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc
.Class
));
1300 switch (desc
.RegisterSet
)
1303 for (i
= 0; i
< count
; i
++)
1305 if (registers_per_matrix
* (i
+ 1) > desc
.RegisterCount
)
1308 hr
= set_float_matrix(matrix
, &desc
, row_offset
, column_offset
, num_rows
, num_columns
, *data
, D3DXPT_FLOAT
, 4);
1309 if (FAILED(hr
)) return hr
;
1311 set_float_shader_constant(This
, device
, desc
.RegisterIndex
+ i
* registers_per_matrix
, matrix
, registers_per_matrix
);
1317 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc
.RegisterSet
));
1324 static HRESULT WINAPI
ID3DXConstantTableImpl_SetDefaults(struct ID3DXConstantTable
*iface
,
1325 struct IDirect3DDevice9
*device
)
1327 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1330 TRACE("(%p)->(%p)\n", This
, device
);
1333 return D3DERR_INVALIDCALL
;
1335 for (i
= 0; i
< This
->desc
.Constants
; i
++)
1337 D3DXCONSTANT_DESC
*desc
= &This
->constants
[i
].desc
;
1339 if (!desc
->DefaultValue
)
1342 set_float_shader_constant(This
, device
, desc
->RegisterIndex
, desc
->DefaultValue
, desc
->RegisterCount
);
1348 static HRESULT WINAPI
ID3DXConstantTableImpl_SetValue(struct ID3DXConstantTable
*iface
,
1349 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const void *data
, UINT bytes
)
1351 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1355 D3DXCONSTANT_DESC desc
;
1357 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, data
, bytes
);
1359 if (!device
|| !constant
|| !data
)
1360 return D3DERR_INVALIDCALL
;
1362 hr
= ID3DXConstantTable_GetConstantDesc(iface
, constant
, &desc
, &count
);
1366 elements
= bytes
/ (desc
.Bytes
/ desc
.Elements
);
1371 return set_scalar_array(iface
, device
, constant
, data
, elements
, desc
.Type
);
1373 return set_vector_array(iface
, device
, constant
, data
, elements
, desc
.Type
);
1374 case D3DXPC_MATRIX_ROWS
:
1375 case D3DXPC_MATRIX_COLUMNS
:
1376 return set_matrix_array(iface
, device
, constant
, data
, elements
,
1377 D3DXPC_MATRIX_ROWS
, desc
.Type
, desc
.Rows
, desc
.Columns
);
1379 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(desc
.Class
));
1380 return D3DERR_INVALIDCALL
;
1384 static HRESULT WINAPI
ID3DXConstantTableImpl_SetBool(struct ID3DXConstantTable
*iface
,
1385 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, BOOL b
)
1387 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1389 TRACE("(%p)->(%p, %p, %d)\n", This
, device
, constant
, b
);
1391 return set_scalar_array(iface
, device
, constant
, &b
, 1, D3DXPT_BOOL
);
1394 static HRESULT WINAPI
ID3DXConstantTableImpl_SetBoolArray(struct ID3DXConstantTable
*iface
,
1395 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const BOOL
*b
, UINT count
)
1397 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1399 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, b
, count
);
1401 return set_scalar_array(iface
, device
, constant
, b
, count
, D3DXPT_BOOL
);
1404 static HRESULT WINAPI
ID3DXConstantTableImpl_SetInt(struct ID3DXConstantTable
*iface
,
1405 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, INT n
)
1407 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1409 TRACE("(%p)->(%p, %p, %d)\n", This
, device
, constant
, n
);
1411 return set_scalar_array(iface
, device
, constant
, &n
, 1, D3DXPT_INT
);
1414 static HRESULT WINAPI
ID3DXConstantTableImpl_SetIntArray(struct ID3DXConstantTable
*iface
,
1415 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const INT
*n
, UINT count
)
1417 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1419 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, n
, count
);
1421 return set_scalar_array(iface
, device
, constant
, n
, count
, D3DXPT_INT
);
1424 static HRESULT WINAPI
ID3DXConstantTableImpl_SetFloat(struct ID3DXConstantTable
*iface
,
1425 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, float f
)
1427 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1429 TRACE("(%p)->(%p, %p, %f)\n", This
, device
, constant
, f
);
1431 return set_scalar_array(iface
, device
, constant
, &f
, 1, D3DXPT_FLOAT
);
1434 static HRESULT WINAPI
ID3DXConstantTableImpl_SetFloatArray(struct ID3DXConstantTable
*iface
,
1435 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const float *f
, UINT count
)
1437 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1439 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, f
, count
);
1441 return set_scalar_array(iface
, device
, constant
, f
, count
, D3DXPT_FLOAT
);
1444 static HRESULT WINAPI
ID3DXConstantTableImpl_SetVector(struct ID3DXConstantTable
*iface
,
1445 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXVECTOR4
*vector
)
1447 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1449 TRACE("(%p)->(%p, %p, %p)\n", This
, device
, constant
, vector
);
1451 return set_vector_array(iface
, device
, constant
, vector
, 1, D3DXPT_FLOAT
);
1454 static HRESULT WINAPI
ID3DXConstantTableImpl_SetVectorArray(struct ID3DXConstantTable
*iface
,
1455 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXVECTOR4
*vector
, UINT count
)
1457 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1459 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, vector
, count
);
1461 return set_vector_array(iface
, device
, constant
, vector
, count
, D3DXPT_FLOAT
);
1464 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrix(struct ID3DXConstantTable
*iface
,
1465 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
*matrix
)
1467 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1469 TRACE("(%p)->(%p, %p, %p)\n", This
, device
, constant
, matrix
);
1471 return set_matrix_array(iface
, device
, constant
, matrix
, 1, D3DXPC_MATRIX_ROWS
, D3DXPT_FLOAT
, 4, 4);
1474 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrixArray(struct ID3DXConstantTable
*iface
,
1475 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
*matrix
, UINT count
)
1477 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1479 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, matrix
, count
);
1481 return set_matrix_array(iface
, device
, constant
, matrix
, count
, D3DXPC_MATRIX_ROWS
, D3DXPT_FLOAT
, 4, 4);
1484 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrixPointerArray(struct ID3DXConstantTable
*iface
,
1485 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
**matrix
, UINT count
)
1487 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1489 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, matrix
, count
);
1491 return set_matrix_pointer_array(iface
, device
, constant
, matrix
, count
, D3DXPC_MATRIX_ROWS
);
1494 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrixTranspose(struct ID3DXConstantTable
*iface
,
1495 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
*matrix
)
1497 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1499 TRACE("(%p)->(%p, %p, %p)\n", This
, device
, constant
, matrix
);
1501 return set_matrix_array(iface
, device
, constant
, matrix
, 1, D3DXPC_MATRIX_COLUMNS
, D3DXPT_FLOAT
, 4, 4);
1504 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrixTransposeArray(struct ID3DXConstantTable
*iface
,
1505 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
*matrix
, UINT count
)
1507 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1509 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, matrix
, count
);
1511 return set_matrix_array(iface
, device
, constant
, matrix
, count
, D3DXPC_MATRIX_COLUMNS
, D3DXPT_FLOAT
, 4, 4);
1514 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrixTransposePointerArray(struct ID3DXConstantTable
*iface
,
1515 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
**matrix
, UINT count
)
1517 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1519 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, matrix
, count
);
1521 return set_matrix_pointer_array(iface
, device
, constant
, matrix
, count
, D3DXPC_MATRIX_COLUMNS
);
1524 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl
=
1526 /*** IUnknown methods ***/
1527 ID3DXConstantTableImpl_QueryInterface
,
1528 ID3DXConstantTableImpl_AddRef
,
1529 ID3DXConstantTableImpl_Release
,
1530 /*** ID3DXBuffer methods ***/
1531 ID3DXConstantTableImpl_GetBufferPointer
,
1532 ID3DXConstantTableImpl_GetBufferSize
,
1533 /*** ID3DXConstantTable methods ***/
1534 ID3DXConstantTableImpl_GetDesc
,
1535 ID3DXConstantTableImpl_GetConstantDesc
,
1536 ID3DXConstantTableImpl_GetSamplerIndex
,
1537 ID3DXConstantTableImpl_GetConstant
,
1538 ID3DXConstantTableImpl_GetConstantByName
,
1539 ID3DXConstantTableImpl_GetConstantElement
,
1540 ID3DXConstantTableImpl_SetDefaults
,
1541 ID3DXConstantTableImpl_SetValue
,
1542 ID3DXConstantTableImpl_SetBool
,
1543 ID3DXConstantTableImpl_SetBoolArray
,
1544 ID3DXConstantTableImpl_SetInt
,
1545 ID3DXConstantTableImpl_SetIntArray
,
1546 ID3DXConstantTableImpl_SetFloat
,
1547 ID3DXConstantTableImpl_SetFloatArray
,
1548 ID3DXConstantTableImpl_SetVector
,
1549 ID3DXConstantTableImpl_SetVectorArray
,
1550 ID3DXConstantTableImpl_SetMatrix
,
1551 ID3DXConstantTableImpl_SetMatrixArray
,
1552 ID3DXConstantTableImpl_SetMatrixPointerArray
,
1553 ID3DXConstantTableImpl_SetMatrixTranspose
,
1554 ID3DXConstantTableImpl_SetMatrixTransposeArray
,
1555 ID3DXConstantTableImpl_SetMatrixTransposePointerArray
1558 static HRESULT
parse_ctab_constant_type(const char *ctab
, DWORD typeoffset
, struct ctab_constant
*constant
,
1559 BOOL is_element
, WORD index
, WORD max
, DWORD
*offset
, DWORD nameoffset
, UINT regset
)
1561 const D3DXSHADER_TYPEINFO
*type
= (LPD3DXSHADER_TYPEINFO
)(ctab
+ typeoffset
);
1562 const D3DXSHADER_STRUCTMEMBERINFO
*memberinfo
= NULL
;
1563 HRESULT hr
= D3D_OK
;
1567 constant
->desc
.DefaultValue
= offset
? ctab
+ *offset
: NULL
;
1568 constant
->desc
.Class
= type
->Class
;
1569 constant
->desc
.Type
= type
->Type
;
1570 constant
->desc
.Rows
= type
->Rows
;
1571 constant
->desc
.Columns
= type
->Columns
;
1572 constant
->desc
.Elements
= is_element
? 1 : type
->Elements
;
1573 constant
->desc
.StructMembers
= type
->StructMembers
;
1574 constant
->desc
.Name
= ctab
+ nameoffset
;
1575 constant
->desc
.RegisterSet
= regset
;
1576 constant
->desc
.RegisterIndex
= index
;
1578 TRACE("name %s, elements %u, index %u, defaultvalue %p, regset %s\n", constant
->desc
.Name
,
1579 constant
->desc
.Elements
, index
, constant
->desc
.DefaultValue
,
1580 debug_d3dxparameter_registerset(regset
));
1581 TRACE("class %s, type %s, rows %d, columns %d, elements %d, struct_members %d\n",
1582 debug_d3dxparameter_class(type
->Class
), debug_d3dxparameter_type(type
->Type
),
1583 type
->Rows
, type
->Columns
, type
->Elements
, type
->StructMembers
);
1585 if (type
->Elements
> 1 && !is_element
)
1587 count
= type
->Elements
;
1589 else if ((type
->Class
== D3DXPC_STRUCT
) && type
->StructMembers
)
1591 memberinfo
= (D3DXSHADER_STRUCTMEMBERINFO
*)(ctab
+ type
->StructMemberInfo
);
1592 count
= type
->StructMembers
;
1597 constant
->constants
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*constant
->constants
) * count
);
1598 if (!constant
->constants
)
1600 ERR("Out of memory\n");
1605 for (i
= 0; i
< count
; ++i
)
1607 hr
= parse_ctab_constant_type(ctab
, memberinfo
? memberinfo
[i
].TypeInfo
: typeoffset
,
1608 &constant
->constants
[i
], memberinfo
== NULL
, index
+ size
, max
, offset
,
1609 memberinfo
? memberinfo
[i
].Name
: nameoffset
, regset
);
1613 size
+= constant
->constants
[i
].desc
.RegisterCount
;
1618 WORD offsetdiff
= 0;
1620 switch (type
->Class
)
1628 case D3DXPC_MATRIX_ROWS
:
1629 size
= is_element
? type
->Rows
: max(type
->Rows
, type
->Columns
);
1630 offsetdiff
= type
->Rows
;
1633 case D3DXPC_MATRIX_COLUMNS
:
1634 size
= type
->Columns
;
1635 offsetdiff
= type
->Columns
;
1643 FIXME("Unhandled type class %s\n", debug_d3dxparameter_class(type
->Class
));
1647 /* offset in bytes => offsetdiff * components(4) * sizeof(DWORD) */
1648 if (offset
) *offset
+= offsetdiff
* 4 * 4;
1650 /* int and bool registerset have different sizes */
1651 if (regset
== D3DXRS_INT4
|| regset
== D3DXRS_BOOL
)
1653 switch (type
->Class
)
1657 size
= type
->Columns
;
1660 case D3DXPC_MATRIX_ROWS
:
1661 case D3DXPC_MATRIX_COLUMNS
:
1662 size
= 4 * type
->Columns
;
1666 FIXME("Unhandled type class %s\n", debug_d3dxparameter_class(type
->Class
));
1672 constant
->desc
.RegisterCount
= max(0, min(max
- index
, size
));
1673 constant
->desc
.Bytes
= 4 * constant
->desc
.Elements
* type
->Rows
* type
->Columns
;
1678 if (constant
->constants
)
1680 for (i
= 0; i
< count
; ++i
)
1682 free_constant(&constant
->constants
[i
]);
1684 HeapFree(GetProcessHeap(), 0, constant
->constants
);
1685 constant
->constants
= NULL
;
1691 HRESULT WINAPI
D3DXGetShaderConstantTableEx(CONST DWORD
*byte_code
,
1693 LPD3DXCONSTANTTABLE
*constant_table
)
1695 struct ID3DXConstantTableImpl
*object
= NULL
;
1699 const D3DXSHADER_CONSTANTTABLE
* ctab_header
;
1700 D3DXSHADER_CONSTANTINFO
* constant_info
;
1703 TRACE("(%p, %x, %p)\n", byte_code
, flags
, constant_table
);
1705 if (!byte_code
|| !constant_table
)
1707 WARN("Invalid argument specified.\n");
1708 return D3DERR_INVALIDCALL
;
1711 if (flags
) FIXME("Flags (%#x) are not handled, yet!\n", flags
);
1713 hr
= D3DXFindShaderComment(byte_code
, MAKEFOURCC('C','T','A','B'), &data
, &size
);
1716 WARN("CTAB not found.\n");
1717 return D3DXERR_INVALIDDATA
;
1720 if (size
< sizeof(D3DXSHADER_CONSTANTTABLE
))
1722 WARN("Invalid CTAB size.\n");
1723 return D3DXERR_INVALIDDATA
;
1726 ctab_header
= (const D3DXSHADER_CONSTANTTABLE
*)data
;
1727 if (ctab_header
->Size
!= sizeof(D3DXSHADER_CONSTANTTABLE
))
1729 WARN("Invalid D3DXSHADER_CONSTANTTABLE size.\n");
1730 return D3DXERR_INVALIDDATA
;
1733 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1736 ERR("Out of memory\n");
1737 return E_OUTOFMEMORY
;
1740 object
->ID3DXConstantTable_iface
.lpVtbl
= &ID3DXConstantTable_Vtbl
;
1743 object
->ctab
= HeapAlloc(GetProcessHeap(), 0, size
);
1746 ERR("Out of memory\n");
1747 HeapFree(GetProcessHeap(), 0, object
);
1748 return E_OUTOFMEMORY
;
1750 object
->size
= size
;
1751 memcpy(object
->ctab
, data
, object
->size
);
1753 object
->desc
.Creator
= ctab_header
->Creator
? object
->ctab
+ ctab_header
->Creator
: NULL
;
1754 object
->desc
.Version
= ctab_header
->Version
;
1755 object
->desc
.Constants
= ctab_header
->Constants
;
1756 TRACE("Creator %s, Version %x, Constants %u, Target %s\n",
1757 debugstr_a(object
->desc
.Creator
), object
->desc
.Version
, object
->desc
.Constants
,
1758 debugstr_a(ctab_header
->Target
? object
->ctab
+ ctab_header
->Target
: NULL
));
1760 object
->constants
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1761 sizeof(*object
->constants
) * object
->desc
.Constants
);
1762 if (!object
->constants
)
1764 ERR("Out of memory\n");
1769 constant_info
= (LPD3DXSHADER_CONSTANTINFO
)(object
->ctab
+ ctab_header
->ConstantInfo
);
1770 for (i
= 0; i
< ctab_header
->Constants
; i
++)
1772 DWORD offset
= constant_info
[i
].DefaultValue
;
1774 hr
= parse_ctab_constant_type(object
->ctab
, constant_info
[i
].TypeInfo
,
1775 &object
->constants
[i
], FALSE
, constant_info
[i
].RegisterIndex
,
1776 constant_info
[i
].RegisterIndex
+ constant_info
[i
].RegisterCount
,
1777 offset
? &offset
: NULL
, constant_info
[i
].Name
, constant_info
[i
].RegisterSet
);
1782 *constant_table
= &object
->ID3DXConstantTable_iface
;
1787 free_constant_table(object
);
1788 HeapFree(GetProcessHeap(), 0, object
);
1793 HRESULT WINAPI
D3DXGetShaderConstantTable(CONST DWORD
* byte_code
,
1794 LPD3DXCONSTANTTABLE
* constant_table
)
1796 TRACE("(%p, %p): Forwarded to D3DXGetShaderConstantTableEx\n", byte_code
, constant_table
);
1798 return D3DXGetShaderConstantTableEx(byte_code
, 0, constant_table
);
1801 HRESULT WINAPI
D3DXGetShaderSamplers(CONST DWORD
*byte_code
, LPCSTR
*samplers
, UINT
*count
)
1804 UINT i
, sampler_count
= 0;
1807 const D3DXSHADER_CONSTANTTABLE
*ctab_header
;
1808 const D3DXSHADER_CONSTANTINFO
*constant_info
;
1810 TRACE("byte_code %p, samplers %p, count %p\n", byte_code
, samplers
, count
);
1812 if (count
) *count
= 0;
1814 hr
= D3DXFindShaderComment(byte_code
, MAKEFOURCC('C','T','A','B'), (LPCVOID
*)&data
, &size
);
1815 if (hr
!= D3D_OK
) return D3D_OK
;
1817 if (size
< sizeof(D3DXSHADER_CONSTANTTABLE
)) return D3D_OK
;
1819 ctab_header
= (const D3DXSHADER_CONSTANTTABLE
*)data
;
1820 if (ctab_header
->Size
!= sizeof(*ctab_header
)) return D3D_OK
;
1822 constant_info
= (D3DXSHADER_CONSTANTINFO
*)(data
+ ctab_header
->ConstantInfo
);
1823 for (i
= 0; i
< ctab_header
->Constants
; i
++)
1825 const D3DXSHADER_TYPEINFO
*type
;
1827 TRACE("name = %s\n", data
+ constant_info
[i
].Name
);
1829 type
= (D3DXSHADER_TYPEINFO
*)(data
+ constant_info
[i
].TypeInfo
);
1831 if (type
->Type
== D3DXPT_SAMPLER
1832 || type
->Type
== D3DXPT_SAMPLER1D
1833 || type
->Type
== D3DXPT_SAMPLER2D
1834 || type
->Type
== D3DXPT_SAMPLER3D
1835 || type
->Type
== D3DXPT_SAMPLERCUBE
)
1837 if (samplers
) samplers
[sampler_count
] = data
+ constant_info
[i
].Name
;
1843 TRACE("Found %u samplers\n", sampler_count
);
1845 if (count
) *count
= sampler_count
;