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 static inline BOOL
is_valid_bytecode(DWORD token
)
45 return (token
& 0xfffe0000) == 0xfffe0000;
48 const char * WINAPI
D3DXGetPixelShaderProfile(struct IDirect3DDevice9
*device
)
52 TRACE("device %p\n", device
);
54 if (!device
) return NULL
;
56 IDirect3DDevice9_GetDeviceCaps(device
,&caps
);
58 switch (caps
.PixelShaderVersion
)
60 case D3DPS_VERSION(1, 1):
63 case D3DPS_VERSION(1, 2):
66 case D3DPS_VERSION(1, 3):
69 case D3DPS_VERSION(1, 4):
72 case D3DPS_VERSION(2, 0):
73 if ((caps
.PS20Caps
.NumTemps
>=22) &&
74 (caps
.PS20Caps
.Caps
&D3DPS20CAPS_ARBITRARYSWIZZLE
) &&
75 (caps
.PS20Caps
.Caps
&D3DPS20CAPS_GRADIENTINSTRUCTIONS
) &&
76 (caps
.PS20Caps
.Caps
&D3DPS20CAPS_PREDICATION
) &&
77 (caps
.PS20Caps
.Caps
&D3DPS20CAPS_NODEPENDENTREADLIMIT
) &&
78 (caps
.PS20Caps
.Caps
&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT
))
82 if ((caps
.PS20Caps
.NumTemps
>=32) &&
83 (caps
.PS20Caps
.Caps
&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT
))
89 case D3DPS_VERSION(3, 0):
96 UINT WINAPI
D3DXGetShaderSize(const DWORD
*byte_code
)
98 const DWORD
*ptr
= byte_code
;
100 TRACE("byte_code %p\n", byte_code
);
104 /* Look for the END token, skipping the VERSION token */
105 while (*++ptr
!= D3DSIO_END
)
108 if ((*ptr
& D3DSI_OPCODE_MASK
) == D3DSIO_COMMENT
)
110 ptr
+= ((*ptr
& D3DSI_COMMENTSIZE_MASK
) >> D3DSI_COMMENTSIZE_SHIFT
);
115 /* Return the shader size in bytes */
116 return (ptr
- byte_code
) * sizeof(*ptr
);
119 DWORD WINAPI
D3DXGetShaderVersion(const DWORD
*byte_code
)
121 TRACE("byte_code %p\n", byte_code
);
123 return byte_code
? *byte_code
: 0;
126 const char * WINAPI
D3DXGetVertexShaderProfile(struct IDirect3DDevice9
*device
)
130 TRACE("device %p\n", device
);
132 if (!device
) return NULL
;
134 IDirect3DDevice9_GetDeviceCaps(device
,&caps
);
136 switch (caps
.VertexShaderVersion
)
138 case D3DVS_VERSION(1, 1):
140 case D3DVS_VERSION(2, 0):
141 if ((caps
.VS20Caps
.NumTemps
>=13) &&
142 (caps
.VS20Caps
.DynamicFlowControlDepth
==24) &&
143 (caps
.VS20Caps
.Caps
&D3DPS20CAPS_PREDICATION
))
148 case D3DVS_VERSION(3, 0):
155 HRESULT WINAPI
D3DXFindShaderComment(const DWORD
*byte_code
, DWORD fourcc
, const void **data
, UINT
*size
)
157 const DWORD
*ptr
= byte_code
;
159 TRACE("byte_code %p, fourcc %x, data %p, size %p\n", byte_code
, fourcc
, data
, size
);
161 if (data
) *data
= NULL
;
164 if (!byte_code
) return D3DERR_INVALIDCALL
;
165 if (!is_valid_bytecode(*byte_code
)) return D3DXERR_INVALIDDATA
;
167 while (*++ptr
!= D3DSIO_END
)
169 /* Check if it is a comment */
170 if ((*ptr
& D3DSI_OPCODE_MASK
) == D3DSIO_COMMENT
)
172 DWORD comment_size
= (*ptr
& D3DSI_COMMENTSIZE_MASK
) >> D3DSI_COMMENTSIZE_SHIFT
;
174 /* Check if this is the comment we are looking for */
175 if (*(ptr
+ 1) == fourcc
)
177 UINT ctab_size
= (comment_size
- 1) * sizeof(DWORD
);
178 LPCVOID ctab_data
= ptr
+ 2;
183 TRACE("Returning comment data at %p with size %d\n", ctab_data
, ctab_size
);
193 HRESULT WINAPI
D3DXAssembleShader(const char *data
, UINT data_len
, const D3DXMACRO
*defines
,
194 ID3DXInclude
*include
, DWORD flags
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
196 /* Forward to d3dcompiler: the parameter types aren't really different,
197 the actual data types are equivalent */
198 HRESULT hr
= D3DAssemble(data
, data_len
, NULL
, (D3D_SHADER_MACRO
*)defines
,
199 (ID3DInclude
*)include
, flags
, (ID3DBlob
**)shader
,
200 (ID3DBlob
**)error_messages
);
202 if(hr
== E_FAIL
) hr
= D3DXERR_INVALIDDATA
;
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(const char *filename
, const D3DXMACRO
*defines
,
280 ID3DXInclude
*include
, DWORD flags
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
282 LPWSTR filename_w
= NULL
;
286 if (!filename
) return D3DXERR_INVALIDDATA
;
288 len
= MultiByteToWideChar(CP_ACP
, 0, filename
, -1, NULL
, 0);
289 filename_w
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
290 if (!filename_w
) return E_OUTOFMEMORY
;
291 MultiByteToWideChar(CP_ACP
, 0, filename
, -1, filename_w
, len
);
293 ret
= D3DXAssembleShaderFromFileW(filename_w
, defines
, include
, flags
, shader
, error_messages
);
295 HeapFree(GetProcessHeap(), 0, filename_w
);
299 HRESULT WINAPI
D3DXAssembleShaderFromFileW(const WCHAR
*filename
, const D3DXMACRO
*defines
,
300 ID3DXInclude
*include
, DWORD flags
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
305 struct D3DXIncludeImpl includefromfile
;
307 if(FAILED(map_view_of_file(filename
, &buffer
, &len
)))
308 return D3DXERR_INVALIDDATA
;
312 includefromfile
.ID3DXInclude_iface
.lpVtbl
= &D3DXInclude_Vtbl
;
313 include
= &includefromfile
.ID3DXInclude_iface
;
316 hr
= D3DXAssembleShader(buffer
, len
, defines
, include
, flags
,
317 shader
, error_messages
);
319 UnmapViewOfFile(buffer
);
323 HRESULT WINAPI
D3DXAssembleShaderFromResourceA(HMODULE module
, const char *resource
, const D3DXMACRO
*defines
,
324 ID3DXInclude
*include
, DWORD flags
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
330 if (!(res
= FindResourceA(module
, resource
, (LPCSTR
)RT_RCDATA
)))
331 return D3DXERR_INVALIDDATA
;
332 if (FAILED(load_resource_into_memory(module
, res
, (LPVOID
*)&buffer
, &len
)))
333 return D3DXERR_INVALIDDATA
;
334 return D3DXAssembleShader(buffer
, len
, defines
, include
, flags
,
335 shader
, error_messages
);
338 HRESULT WINAPI
D3DXAssembleShaderFromResourceW(HMODULE module
, const WCHAR
*resource
, const D3DXMACRO
*defines
,
339 ID3DXInclude
*include
, DWORD flags
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
345 if (!(res
= FindResourceW(module
, resource
, (LPCWSTR
)RT_RCDATA
)))
346 return D3DXERR_INVALIDDATA
;
347 if (FAILED(load_resource_into_memory(module
, res
, (LPVOID
*)&buffer
, &len
)))
348 return D3DXERR_INVALIDDATA
;
349 return D3DXAssembleShader(buffer
, len
, defines
, include
, flags
,
350 shader
, error_messages
);
353 HRESULT WINAPI
D3DXCompileShader(const char *pSrcData
, UINT srcDataLen
, const D3DXMACRO
*pDefines
,
354 ID3DXInclude
*pInclude
, const char *pFunctionName
, const char *pProfile
, DWORD Flags
,
355 ID3DXBuffer
**ppShader
, ID3DXBuffer
**ppErrorMsgs
, ID3DXConstantTable
**ppConstantTable
)
357 HRESULT hr
= D3DCompile(pSrcData
, srcDataLen
, NULL
,
358 (D3D_SHADER_MACRO
*)pDefines
, (ID3DInclude
*)pInclude
,
359 pFunctionName
, pProfile
, Flags
, 0,
360 (ID3DBlob
**)ppShader
, (ID3DBlob
**)ppErrorMsgs
);
362 if(SUCCEEDED(hr
) && ppConstantTable
)
363 return D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*ppShader
),
368 HRESULT WINAPI
D3DXCompileShaderFromFileA(const char *filename
, const D3DXMACRO
*defines
,
369 ID3DXInclude
*include
, const char *entrypoint
, const char *profile
, DWORD flags
,
370 ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
, ID3DXConstantTable
**constant_table
)
372 LPWSTR filename_w
= NULL
;
376 if (!filename
) return D3DXERR_INVALIDDATA
;
378 len
= MultiByteToWideChar(CP_ACP
, 0, filename
, -1, NULL
, 0);
379 filename_w
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
380 if (!filename_w
) return E_OUTOFMEMORY
;
381 MultiByteToWideChar(CP_ACP
, 0, filename
, -1, filename_w
, len
);
383 ret
= D3DXCompileShaderFromFileW(filename_w
, defines
, include
,
384 entrypoint
, profile
, flags
,
385 shader
, error_messages
, constant_table
);
387 HeapFree(GetProcessHeap(), 0, filename_w
);
391 HRESULT WINAPI
D3DXCompileShaderFromFileW(const WCHAR
*filename
, const D3DXMACRO
*defines
,
392 ID3DXInclude
*include
, const char *entrypoint
, const char *profile
, DWORD flags
,
393 ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
, ID3DXConstantTable
**constant_table
)
396 DWORD len
, filename_len
;
398 struct D3DXIncludeImpl includefromfile
;
401 if (FAILED(map_view_of_file(filename
, &buffer
, &len
)))
402 return D3DXERR_INVALIDDATA
;
406 includefromfile
.ID3DXInclude_iface
.lpVtbl
= &D3DXInclude_Vtbl
;
407 include
= &includefromfile
.ID3DXInclude_iface
;
410 filename_len
= WideCharToMultiByte(CP_ACP
, 0, filename
, -1, NULL
, 0, NULL
, NULL
);
411 filename_a
= HeapAlloc(GetProcessHeap(), 0, filename_len
* sizeof(char));
414 UnmapViewOfFile(buffer
);
415 return E_OUTOFMEMORY
;
417 WideCharToMultiByte(CP_ACP
, 0, filename
, -1, filename_a
, filename_len
, NULL
, NULL
);
419 hr
= D3DCompile(buffer
, len
, filename_a
, (const D3D_SHADER_MACRO
*)defines
,
420 (ID3DInclude
*)include
, entrypoint
, profile
, flags
, 0,
421 (ID3DBlob
**)shader
, (ID3DBlob
**)error_messages
);
423 if (SUCCEEDED(hr
) && constant_table
)
424 hr
= D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader
),
427 HeapFree(GetProcessHeap(), 0, filename_a
);
428 UnmapViewOfFile(buffer
);
432 HRESULT WINAPI
D3DXCompileShaderFromResourceA(HMODULE module
, const char *resource
, const D3DXMACRO
*defines
,
433 ID3DXInclude
*include
, const char *entrypoint
, const char *profile
, DWORD flags
,
434 ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
, ID3DXConstantTable
**constant_table
)
440 if (!(res
= FindResourceA(module
, resource
, (LPCSTR
)RT_RCDATA
)))
441 return D3DXERR_INVALIDDATA
;
442 if (FAILED(load_resource_into_memory(module
, res
, (LPVOID
*)&buffer
, &len
)))
443 return D3DXERR_INVALIDDATA
;
444 return D3DXCompileShader(buffer
, len
, defines
, include
, entrypoint
, profile
,
445 flags
, shader
, error_messages
, constant_table
);
448 HRESULT WINAPI
D3DXCompileShaderFromResourceW(HMODULE module
, const WCHAR
*resource
, const D3DXMACRO
*defines
,
449 ID3DXInclude
*include
, const char *entrypoint
, const char *profile
, DWORD flags
,
450 ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
, ID3DXConstantTable
**constant_table
)
456 if (!(res
= FindResourceW(module
, resource
, (LPCWSTR
)RT_RCDATA
)))
457 return D3DXERR_INVALIDDATA
;
458 if (FAILED(load_resource_into_memory(module
, res
, (LPVOID
*)&buffer
, &len
)))
459 return D3DXERR_INVALIDDATA
;
460 return D3DXCompileShader(buffer
, len
, defines
, include
, entrypoint
, profile
,
461 flags
, shader
, error_messages
, constant_table
);
464 HRESULT WINAPI
D3DXPreprocessShader(const char *data
, UINT data_len
, const D3DXMACRO
*defines
,
465 ID3DXInclude
*include
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
467 TRACE("Forward to D3DPreprocess\n");
468 return D3DPreprocess(data
, data_len
, NULL
,
469 (const D3D_SHADER_MACRO
*)defines
, (ID3DInclude
*)include
,
470 (ID3DBlob
**)shader
, (ID3DBlob
**)error_messages
);
473 HRESULT WINAPI
D3DXPreprocessShaderFromFileA(const char *filename
, const D3DXMACRO
*defines
,
474 ID3DXInclude
*include
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
476 WCHAR
*filename_w
= NULL
;
480 if (!filename
) return D3DXERR_INVALIDDATA
;
482 len
= MultiByteToWideChar(CP_ACP
, 0, filename
, -1, NULL
, 0);
483 filename_w
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
484 if (!filename_w
) return E_OUTOFMEMORY
;
485 MultiByteToWideChar(CP_ACP
, 0, filename
, -1, filename_w
, len
);
487 ret
= D3DXPreprocessShaderFromFileW(filename_w
, defines
, include
, shader
, error_messages
);
489 HeapFree(GetProcessHeap(), 0, filename_w
);
493 HRESULT WINAPI
D3DXPreprocessShaderFromFileW(const WCHAR
*filename
, const D3DXMACRO
*defines
,
494 ID3DXInclude
*include
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
499 struct D3DXIncludeImpl includefromfile
;
501 if (FAILED(map_view_of_file(filename
, &buffer
, &len
)))
502 return D3DXERR_INVALIDDATA
;
506 includefromfile
.ID3DXInclude_iface
.lpVtbl
= &D3DXInclude_Vtbl
;
507 include
= &includefromfile
.ID3DXInclude_iface
;
510 hr
= D3DPreprocess(buffer
, len
, NULL
,
511 (const D3D_SHADER_MACRO
*)defines
,
512 (ID3DInclude
*) include
,
513 (ID3DBlob
**)shader
, (ID3DBlob
**)error_messages
);
515 UnmapViewOfFile(buffer
);
519 HRESULT WINAPI
D3DXPreprocessShaderFromResourceA(HMODULE module
, const char *resource
, const D3DXMACRO
*defines
,
520 ID3DXInclude
*include
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
526 if (!(res
= FindResourceA(module
, resource
, (LPCSTR
)RT_RCDATA
)))
527 return D3DXERR_INVALIDDATA
;
528 if (FAILED(load_resource_into_memory(module
, res
, (LPVOID
*)&buffer
, &len
)))
529 return D3DXERR_INVALIDDATA
;
530 return D3DXPreprocessShader(buffer
, len
, defines
, include
,
531 shader
, error_messages
);
534 HRESULT WINAPI
D3DXPreprocessShaderFromResourceW(HMODULE module
, const WCHAR
*resource
, const D3DXMACRO
*defines
,
535 ID3DXInclude
*include
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
541 if (!(res
= FindResourceW(module
, resource
, (const WCHAR
*)RT_RCDATA
)))
542 return D3DXERR_INVALIDDATA
;
543 if (FAILED(load_resource_into_memory(module
, res
, (void **)&buffer
, &len
)))
544 return D3DXERR_INVALIDDATA
;
545 return D3DXPreprocessShader(buffer
, len
, defines
, include
,
546 shader
, error_messages
);
550 struct ctab_constant
{
551 D3DXCONSTANT_DESC desc
;
552 struct ctab_constant
*constants
;
555 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl
;
557 struct ID3DXConstantTableImpl
{
558 ID3DXConstantTable ID3DXConstantTable_iface
;
562 D3DXCONSTANTTABLE_DESC desc
;
563 struct ctab_constant
*constants
;
566 static void free_constant(struct ctab_constant
*constant
)
568 if (constant
->constants
)
570 UINT i
, count
= constant
->desc
.Elements
> 1 ? constant
->desc
.Elements
: constant
->desc
.StructMembers
;
572 for (i
= 0; i
< count
; ++i
)
574 free_constant(&constant
->constants
[i
]);
576 HeapFree(GetProcessHeap(), 0, constant
->constants
);
580 static void free_constant_table(struct ID3DXConstantTableImpl
*table
)
582 if (table
->constants
)
586 for (i
= 0; i
< table
->desc
.Constants
; ++i
)
588 free_constant(&table
->constants
[i
]);
590 HeapFree(GetProcessHeap(), 0, table
->constants
);
592 HeapFree(GetProcessHeap(), 0, table
->ctab
);
595 static inline struct ID3DXConstantTableImpl
*impl_from_ID3DXConstantTable(ID3DXConstantTable
*iface
)
597 return CONTAINING_RECORD(iface
, struct ID3DXConstantTableImpl
, ID3DXConstantTable_iface
);
600 static inline BOOL
is_vertex_shader(DWORD version
)
602 return (version
& 0xffff0000) == 0xfffe0000;
605 static inline struct ctab_constant
*constant_from_handle(D3DXHANDLE handle
)
607 return (struct ctab_constant
*)handle
;
610 static inline D3DXHANDLE
handle_from_constant(struct ctab_constant
*constant
)
612 return (D3DXHANDLE
)constant
;
615 static struct ctab_constant
*get_constant_by_name(struct ID3DXConstantTableImpl
*, struct ctab_constant
*, LPCSTR
);
617 static struct ctab_constant
*get_constant_element_by_name(struct ctab_constant
*constant
, LPCSTR name
)
622 TRACE("constant %p, name %s\n", constant
, debugstr_a(name
));
624 if (!name
|| !*name
) return NULL
;
626 element
= atoi(name
);
627 part
= strchr(name
, ']') + 1;
629 if (constant
->desc
.Elements
> element
)
631 struct ctab_constant
*c
= constant
->constants
? &constant
->constants
[element
] : constant
;
636 return get_constant_by_name(NULL
, c
, part
);
639 return get_constant_element_by_name(c
, part
);
642 TRACE("Returning parameter %p\n", c
);
646 FIXME("Unhandled case \"%c\"\n", *--part
);
651 TRACE("Constant not found\n");
655 static struct ctab_constant
*get_constant_by_name(struct ID3DXConstantTableImpl
*table
,
656 struct ctab_constant
*constant
, LPCSTR name
)
658 UINT i
, count
, length
;
659 struct ctab_constant
*handles
;
662 TRACE("table %p, constant %p, name %s\n", table
, constant
, debugstr_a(name
));
664 if (!name
|| !*name
) return NULL
;
668 count
= table
->desc
.Constants
;
669 handles
= table
->constants
;
673 count
= constant
->desc
.StructMembers
;
674 handles
= constant
->constants
;
677 length
= strcspn(name
, "[.");
678 part
= name
+ length
;
680 for (i
= 0; i
< count
; i
++)
682 if (strlen(handles
[i
].desc
.Name
) == length
&& !strncmp(handles
[i
].desc
.Name
, name
, length
))
687 return get_constant_by_name(NULL
, &handles
[i
], part
);
690 return get_constant_element_by_name(&handles
[i
], part
);
693 TRACE("Returning parameter %p\n", &handles
[i
]);
699 TRACE("Constant not found\n");
703 static struct ctab_constant
*is_valid_sub_constant(struct ctab_constant
*parent
, struct ctab_constant
*constant
)
707 /* all variable have at least elements = 1, but no elements */
708 if (!parent
->constants
) return NULL
;
710 if (parent
->desc
.Elements
> 1) count
= parent
->desc
.Elements
;
711 else count
= parent
->desc
.StructMembers
;
713 for (i
= 0; i
< count
; ++i
)
715 if (&parent
->constants
[i
] == constant
)
718 if (is_valid_sub_constant(&parent
->constants
[i
], constant
))
725 static inline struct ctab_constant
*is_valid_constant(struct ID3DXConstantTableImpl
*table
, D3DXHANDLE handle
)
727 struct ctab_constant
*c
= constant_from_handle(handle
);
732 for (i
= 0; i
< table
->desc
.Constants
; ++i
)
734 if (&table
->constants
[i
] == c
)
737 if (is_valid_sub_constant(&table
->constants
[i
], c
))
744 static inline struct ctab_constant
*get_valid_constant(struct ID3DXConstantTableImpl
*table
, D3DXHANDLE handle
)
746 struct ctab_constant
*constant
= is_valid_constant(table
, handle
);
748 if (!constant
) constant
= get_constant_by_name(table
, NULL
, handle
);
753 static inline void set_float_shader_constant(struct ID3DXConstantTableImpl
*table
, IDirect3DDevice9
*device
,
754 UINT register_index
, const FLOAT
*data
, UINT count
)
756 if (is_vertex_shader(table
->desc
.Version
))
757 IDirect3DDevice9_SetVertexShaderConstantF(device
, register_index
, data
, count
);
759 IDirect3DDevice9_SetPixelShaderConstantF(device
, register_index
, data
, count
);
762 /*** IUnknown methods ***/
763 static HRESULT WINAPI
ID3DXConstantTableImpl_QueryInterface(ID3DXConstantTable
*iface
, REFIID riid
, void **out
)
765 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
767 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
768 IsEqualGUID(riid
, &IID_ID3DXBuffer
) ||
769 IsEqualGUID(riid
, &IID_ID3DXConstantTable
))
771 ID3DXConstantTable_AddRef(iface
);
776 WARN("Interface %s not found.\n", debugstr_guid(riid
));
778 return E_NOINTERFACE
;
781 static ULONG WINAPI
ID3DXConstantTableImpl_AddRef(ID3DXConstantTable
*iface
)
783 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
785 TRACE("(%p)->(): AddRef from %d\n", This
, This
->ref
);
787 return InterlockedIncrement(&This
->ref
);
790 static ULONG WINAPI
ID3DXConstantTableImpl_Release(ID3DXConstantTable
*iface
)
792 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
793 ULONG ref
= InterlockedDecrement(&This
->ref
);
795 TRACE("(%p)->(): Release from %d\n", This
, ref
+ 1);
799 free_constant_table(This
);
800 HeapFree(GetProcessHeap(), 0, This
);
806 /*** ID3DXBuffer methods ***/
807 static LPVOID WINAPI
ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable
*iface
)
809 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
811 TRACE("(%p)->()\n", This
);
816 static DWORD WINAPI
ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable
*iface
)
818 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
820 TRACE("(%p)->()\n", This
);
825 /*** ID3DXConstantTable methods ***/
826 static HRESULT WINAPI
ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable
*iface
, D3DXCONSTANTTABLE_DESC
*desc
)
828 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
830 TRACE("(%p)->(%p)\n", This
, desc
);
833 return D3DERR_INVALIDCALL
;
840 static HRESULT WINAPI
ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable
*iface
, D3DXHANDLE constant
,
841 D3DXCONSTANT_DESC
*desc
, UINT
*count
)
843 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
844 struct ctab_constant
*c
= get_valid_constant(This
, constant
);
846 TRACE("(%p)->(%p, %p, %p)\n", This
, constant
, desc
, count
);
850 WARN("Invalid argument specified\n");
851 return D3DERR_INVALIDCALL
;
854 if (desc
) *desc
= c
->desc
;
855 if (count
) *count
= 1;
860 static UINT WINAPI
ID3DXConstantTableImpl_GetSamplerIndex(ID3DXConstantTable
*iface
, D3DXHANDLE constant
)
862 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
863 struct ctab_constant
*c
= get_valid_constant(This
, constant
);
865 TRACE("(%p)->(%p)\n", This
, constant
);
867 if (!c
|| c
->desc
.RegisterSet
!= D3DXRS_SAMPLER
)
869 WARN("Invalid argument specified\n");
873 TRACE("Returning RegisterIndex %u\n", c
->desc
.RegisterIndex
);
874 return c
->desc
.RegisterIndex
;
877 static D3DXHANDLE WINAPI
ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable
*iface
, D3DXHANDLE constant
, UINT index
)
879 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
880 struct ctab_constant
*c
;
882 TRACE("(%p)->(%p, %d)\n", This
, constant
, index
);
886 c
= get_valid_constant(This
, constant
);
887 if (c
&& index
< c
->desc
.StructMembers
)
889 c
= &c
->constants
[index
];
890 TRACE("Returning constant %p\n", c
);
891 return handle_from_constant(c
);
896 if (index
< This
->desc
.Constants
)
898 c
= &This
->constants
[index
];
899 TRACE("Returning constant %p\n", c
);
900 return handle_from_constant(c
);
904 WARN("Index out of range\n");
908 static D3DXHANDLE WINAPI
ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable
*iface
, D3DXHANDLE constant
, LPCSTR name
)
910 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
911 struct ctab_constant
*c
= get_valid_constant(This
, constant
);
913 TRACE("(%p)->(%p, %s)\n", This
, constant
, name
);
915 c
= get_constant_by_name(This
, c
, name
);
916 TRACE("Returning constant %p\n", c
);
918 return handle_from_constant(c
);
921 static D3DXHANDLE WINAPI
ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable
*iface
, D3DXHANDLE constant
, UINT index
)
923 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
924 struct ctab_constant
*c
= get_valid_constant(This
, constant
);
926 TRACE("(%p)->(%p, %d)\n", This
, constant
, index
);
928 if (c
&& index
< c
->desc
.Elements
)
930 if (c
->desc
.Elements
> 1) c
= &c
->constants
[index
];
931 TRACE("Returning constant %p\n", c
);
932 return handle_from_constant(c
);
935 WARN("Invalid argument specified\n");
939 static HRESULT
set_scalar_array(ID3DXConstantTable
*iface
, IDirect3DDevice9
*device
, D3DXHANDLE constant
, const void *data
,
940 UINT count
, D3DXPARAMETER_TYPE type
)
942 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
943 D3DXCONSTANT_DESC desc
;
945 UINT i
, desc_count
= 1;
946 float row
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
948 hr
= ID3DXConstantTable_GetConstantDesc(iface
, constant
, &desc
, &desc_count
);
951 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr
);
952 return D3DERR_INVALIDCALL
;
955 if (desc
.Class
!= D3DXPC_SCALAR
)
958 switch (desc
.RegisterSet
)
961 for (i
= 0; i
< min(count
, desc
.RegisterCount
); i
++)
963 /* We need the for loop since each IDirect3DDevice9_Set*ShaderConstantF expects a float4 */
967 row
[0] = ((float *)data
)[i
];
970 row
[0] = (float)((int *)data
)[i
];
973 row
[0] = ((BOOL
*)data
)[i
] ? 1.0f
: 0.0f
;
976 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(type
));
977 return D3DERR_INVALIDCALL
;
979 set_float_shader_constant(This
, device
, desc
.RegisterIndex
+ i
, row
, 1);
983 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc
.RegisterSet
));
990 static HRESULT
set_vector_array(ID3DXConstantTable
*iface
, IDirect3DDevice9
*device
, D3DXHANDLE constant
, const void *data
,
991 UINT count
, D3DXPARAMETER_TYPE type
)
993 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
994 D3DXCONSTANT_DESC desc
;
996 UINT i
, j
, desc_count
= 1;
997 float vec
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
999 hr
= ID3DXConstantTable_GetConstantDesc(iface
, constant
, &desc
, &desc_count
);
1002 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr
);
1003 return D3DERR_INVALIDCALL
;
1006 if (desc
.Class
== D3DXPC_MATRIX_ROWS
|| desc
.Class
== D3DXPC_MATRIX_COLUMNS
)
1009 switch (desc
.RegisterSet
)
1012 for (i
= 0; i
< min(count
, desc
.RegisterCount
); i
++)
1017 memcpy(vec
, ((float *)data
) + i
* desc
.Columns
, desc
.Columns
* sizeof(float));
1020 for (j
= 0; j
< desc
.Columns
; j
++)
1021 vec
[j
] = (float)((int *)data
)[i
* desc
.Columns
+ j
];
1024 for (j
= 0; j
< desc
.Columns
; j
++)
1025 vec
[j
] = ((BOOL
*)data
)[i
* desc
.Columns
+ j
] ? 1.0f
: 0.0f
;
1028 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(type
));
1029 return D3DERR_INVALIDCALL
;
1032 set_float_shader_constant(This
, device
, desc
.RegisterIndex
+ i
, vec
, 1);
1036 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc
.RegisterSet
));
1043 static HRESULT
set_float_matrix(FLOAT
*matrix
, const D3DXCONSTANT_DESC
*desc
,
1044 UINT row_offset
, UINT column_offset
, UINT rows
, UINT columns
,
1045 const void *data
, D3DXPARAMETER_TYPE type
, UINT src_columns
)
1052 for (i
= 0; i
< rows
; i
++)
1054 for (j
= 0; j
< columns
; j
++)
1055 matrix
[i
* row_offset
+ j
* column_offset
] = ((FLOAT
*)data
)[i
* src_columns
+ j
];
1059 for (i
= 0; i
< rows
; i
++)
1061 for (j
= 0; j
< columns
; j
++)
1062 matrix
[i
* row_offset
+ j
* column_offset
] = ((INT
*)data
)[i
* src_columns
+ j
];
1066 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(type
));
1067 return D3DERR_INVALIDCALL
;
1073 static HRESULT
set_matrix_array(ID3DXConstantTable
*iface
, IDirect3DDevice9
*device
, D3DXHANDLE constant
, const void *data
,
1074 UINT count
, D3DXPARAMETER_CLASS
class, D3DXPARAMETER_TYPE type
, UINT rows
, UINT columns
)
1076 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1077 struct ctab_constant
*c
= get_valid_constant(This
, constant
);
1078 D3DXCONSTANT_DESC
*desc
;
1079 UINT registers_per_matrix
, num_rows
, num_columns
, i
;
1080 UINT row_offset
= 1, column_offset
= 1;
1081 const DWORD
*data_ptr
;
1082 FLOAT matrix
[16] = {0.0f
, 0.0f
, 0.0f
, 0.0f
,
1083 0.0f
, 0.0f
, 0.0f
, 0.0f
,
1084 0.0f
, 0.0f
, 0.0f
, 0.0f
,
1085 0.0f
, 0.0f
, 0.0f
, 0.0f
};
1089 WARN("Invalid argument specified\n");
1090 return D3DERR_INVALIDCALL
;
1094 if (desc
->Class
== D3DXPC_MATRIX_ROWS
1095 || desc
->Class
== D3DXPC_MATRIX_COLUMNS
1096 || desc
->Class
== D3DXPC_VECTOR
1097 || desc
->Class
== D3DXPC_SCALAR
)
1099 if (desc
->Class
== class) row_offset
= 4;
1100 else column_offset
= 4;
1102 if (class == D3DXPC_MATRIX_ROWS
)
1104 if (desc
->Class
== D3DXPC_VECTOR
) return D3D_OK
;
1106 num_rows
= desc
->Rows
;
1107 num_columns
= desc
->Columns
;
1111 num_rows
= desc
->Columns
;
1112 num_columns
= desc
->Rows
;
1115 registers_per_matrix
= (desc
->Class
== D3DXPC_MATRIX_COLUMNS
) ? desc
->Columns
: desc
->Rows
;
1119 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc
->Class
));
1123 switch (desc
->RegisterSet
)
1127 for (i
= 0; i
< count
; i
++)
1131 if (registers_per_matrix
* (i
+ 1) > desc
->RegisterCount
)
1134 hr
= set_float_matrix(matrix
, desc
, row_offset
, column_offset
, num_rows
, num_columns
, data_ptr
, type
, columns
);
1135 if (FAILED(hr
)) return hr
;
1137 set_float_shader_constant(This
, device
, desc
->RegisterIndex
+ i
* registers_per_matrix
, matrix
, registers_per_matrix
);
1139 data_ptr
+= rows
* columns
;
1143 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc
->RegisterSet
));
1150 static HRESULT
set_matrix_pointer_array(ID3DXConstantTable
*iface
, IDirect3DDevice9
*device
, D3DXHANDLE constant
,
1151 const D3DXMATRIX
**data
, UINT count
, D3DXPARAMETER_CLASS
class)
1153 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1154 D3DXCONSTANT_DESC desc
;
1156 UINT registers_per_matrix
;
1157 UINT i
, desc_count
= 1;
1158 UINT num_rows
, num_columns
;
1159 UINT row_offset
, column_offset
;
1160 FLOAT matrix
[16] = {0.0f
, 0.0f
, 0.0f
, 0.0f
,
1161 0.0f
, 0.0f
, 0.0f
, 0.0f
,
1162 0.0f
, 0.0f
, 0.0f
, 0.0f
,
1163 0.0f
, 0.0f
, 0.0f
, 0.0f
};
1165 hr
= ID3DXConstantTable_GetConstantDesc(iface
, constant
, &desc
, &desc_count
);
1168 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr
);
1169 return D3DERR_INVALIDCALL
;
1172 if (desc
.Class
== D3DXPC_MATRIX_ROWS
|| desc
.Class
== D3DXPC_MATRIX_COLUMNS
)
1174 if (desc
.Class
== class)
1185 if (class == D3DXPC_MATRIX_ROWS
)
1187 num_rows
= desc
.Rows
;
1188 num_columns
= desc
.Columns
;
1192 num_rows
= desc
.Columns
;
1193 num_columns
= desc
.Rows
;
1196 registers_per_matrix
= (desc
.Class
== D3DXPC_MATRIX_ROWS
) ? desc
.Rows
: desc
.Columns
;
1198 else if (desc
.Class
== D3DXPC_SCALAR
)
1200 registers_per_matrix
= 1;
1203 num_rows
= desc
.Rows
;
1204 num_columns
= desc
.Columns
;
1206 else if (desc
.Class
== D3DXPC_VECTOR
)
1208 registers_per_matrix
= 1;
1210 if (class == D3DXPC_MATRIX_ROWS
)
1214 num_rows
= desc
.Rows
;
1215 num_columns
= desc
.Columns
;
1221 num_rows
= desc
.Columns
;
1222 num_columns
= desc
.Rows
;
1227 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc
.Class
));
1231 switch (desc
.RegisterSet
)
1234 for (i
= 0; i
< count
; i
++)
1236 if (registers_per_matrix
* (i
+ 1) > desc
.RegisterCount
)
1239 hr
= set_float_matrix(matrix
, &desc
, row_offset
, column_offset
, num_rows
, num_columns
, *data
, D3DXPT_FLOAT
, 4);
1240 if (FAILED(hr
)) return hr
;
1242 set_float_shader_constant(This
, device
, desc
.RegisterIndex
+ i
* registers_per_matrix
, matrix
, registers_per_matrix
);
1248 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc
.RegisterSet
));
1255 static HRESULT WINAPI
ID3DXConstantTableImpl_SetDefaults(struct ID3DXConstantTable
*iface
,
1256 struct IDirect3DDevice9
*device
)
1258 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1261 TRACE("(%p)->(%p)\n", This
, device
);
1264 return D3DERR_INVALIDCALL
;
1266 for (i
= 0; i
< This
->desc
.Constants
; i
++)
1268 D3DXCONSTANT_DESC
*desc
= &This
->constants
[i
].desc
;
1270 if (!desc
->DefaultValue
)
1273 set_float_shader_constant(This
, device
, desc
->RegisterIndex
, desc
->DefaultValue
, desc
->RegisterCount
);
1279 static HRESULT WINAPI
ID3DXConstantTableImpl_SetValue(struct ID3DXConstantTable
*iface
,
1280 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const void *data
, UINT bytes
)
1282 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1286 D3DXCONSTANT_DESC desc
;
1288 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, data
, bytes
);
1290 if (!device
|| !constant
|| !data
)
1291 return D3DERR_INVALIDCALL
;
1293 hr
= ID3DXConstantTable_GetConstantDesc(iface
, constant
, &desc
, &count
);
1297 elements
= bytes
/ (desc
.Bytes
/ desc
.Elements
);
1302 return set_scalar_array(iface
, device
, constant
, data
, elements
, desc
.Type
);
1304 return set_vector_array(iface
, device
, constant
, data
, elements
, desc
.Type
);
1305 case D3DXPC_MATRIX_ROWS
:
1306 case D3DXPC_MATRIX_COLUMNS
:
1307 return set_matrix_array(iface
, device
, constant
, data
, elements
,
1308 D3DXPC_MATRIX_ROWS
, desc
.Type
, desc
.Rows
, desc
.Columns
);
1310 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(desc
.Class
));
1311 return D3DERR_INVALIDCALL
;
1315 static HRESULT WINAPI
ID3DXConstantTableImpl_SetBool(struct ID3DXConstantTable
*iface
,
1316 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, BOOL b
)
1318 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1320 TRACE("(%p)->(%p, %p, %d)\n", This
, device
, constant
, b
);
1322 return set_scalar_array(iface
, device
, constant
, &b
, 1, D3DXPT_BOOL
);
1325 static HRESULT WINAPI
ID3DXConstantTableImpl_SetBoolArray(struct ID3DXConstantTable
*iface
,
1326 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const BOOL
*b
, UINT count
)
1328 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1330 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, b
, count
);
1332 return set_scalar_array(iface
, device
, constant
, b
, count
, D3DXPT_BOOL
);
1335 static HRESULT WINAPI
ID3DXConstantTableImpl_SetInt(struct ID3DXConstantTable
*iface
,
1336 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, INT n
)
1338 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1340 TRACE("(%p)->(%p, %p, %d)\n", This
, device
, constant
, n
);
1342 return set_scalar_array(iface
, device
, constant
, &n
, 1, D3DXPT_INT
);
1345 static HRESULT WINAPI
ID3DXConstantTableImpl_SetIntArray(struct ID3DXConstantTable
*iface
,
1346 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const INT
*n
, UINT count
)
1348 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1350 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, n
, count
);
1352 return set_scalar_array(iface
, device
, constant
, n
, count
, D3DXPT_INT
);
1355 static HRESULT WINAPI
ID3DXConstantTableImpl_SetFloat(struct ID3DXConstantTable
*iface
,
1356 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, float f
)
1358 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1360 TRACE("(%p)->(%p, %p, %f)\n", This
, device
, constant
, f
);
1362 return set_scalar_array(iface
, device
, constant
, &f
, 1, D3DXPT_FLOAT
);
1365 static HRESULT WINAPI
ID3DXConstantTableImpl_SetFloatArray(struct ID3DXConstantTable
*iface
,
1366 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const float *f
, UINT count
)
1368 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1370 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, f
, count
);
1372 return set_scalar_array(iface
, device
, constant
, f
, count
, D3DXPT_FLOAT
);
1375 static HRESULT WINAPI
ID3DXConstantTableImpl_SetVector(struct ID3DXConstantTable
*iface
,
1376 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXVECTOR4
*vector
)
1378 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1380 TRACE("(%p)->(%p, %p, %p)\n", This
, device
, constant
, vector
);
1382 return set_vector_array(iface
, device
, constant
, vector
, 1, D3DXPT_FLOAT
);
1385 static HRESULT WINAPI
ID3DXConstantTableImpl_SetVectorArray(struct ID3DXConstantTable
*iface
,
1386 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXVECTOR4
*vector
, UINT count
)
1388 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1390 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, vector
, count
);
1392 return set_vector_array(iface
, device
, constant
, vector
, count
, D3DXPT_FLOAT
);
1395 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrix(struct ID3DXConstantTable
*iface
,
1396 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
*matrix
)
1398 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1400 TRACE("(%p)->(%p, %p, %p)\n", This
, device
, constant
, matrix
);
1402 return set_matrix_array(iface
, device
, constant
, matrix
, 1, D3DXPC_MATRIX_ROWS
, D3DXPT_FLOAT
, 4, 4);
1405 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrixArray(struct ID3DXConstantTable
*iface
,
1406 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
*matrix
, UINT count
)
1408 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1410 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, matrix
, count
);
1412 return set_matrix_array(iface
, device
, constant
, matrix
, count
, D3DXPC_MATRIX_ROWS
, D3DXPT_FLOAT
, 4, 4);
1415 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrixPointerArray(struct ID3DXConstantTable
*iface
,
1416 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
**matrix
, UINT count
)
1418 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1420 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, matrix
, count
);
1422 return set_matrix_pointer_array(iface
, device
, constant
, matrix
, count
, D3DXPC_MATRIX_ROWS
);
1425 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrixTranspose(struct ID3DXConstantTable
*iface
,
1426 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
*matrix
)
1428 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1430 TRACE("(%p)->(%p, %p, %p)\n", This
, device
, constant
, matrix
);
1432 return set_matrix_array(iface
, device
, constant
, matrix
, 1, D3DXPC_MATRIX_COLUMNS
, D3DXPT_FLOAT
, 4, 4);
1435 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrixTransposeArray(struct ID3DXConstantTable
*iface
,
1436 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
*matrix
, UINT count
)
1438 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1440 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, matrix
, count
);
1442 return set_matrix_array(iface
, device
, constant
, matrix
, count
, D3DXPC_MATRIX_COLUMNS
, D3DXPT_FLOAT
, 4, 4);
1445 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrixTransposePointerArray(struct ID3DXConstantTable
*iface
,
1446 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
**matrix
, UINT count
)
1448 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1450 TRACE("(%p)->(%p, %p, %p, %d)\n", This
, device
, constant
, matrix
, count
);
1452 return set_matrix_pointer_array(iface
, device
, constant
, matrix
, count
, D3DXPC_MATRIX_COLUMNS
);
1455 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl
=
1457 /*** IUnknown methods ***/
1458 ID3DXConstantTableImpl_QueryInterface
,
1459 ID3DXConstantTableImpl_AddRef
,
1460 ID3DXConstantTableImpl_Release
,
1461 /*** ID3DXBuffer methods ***/
1462 ID3DXConstantTableImpl_GetBufferPointer
,
1463 ID3DXConstantTableImpl_GetBufferSize
,
1464 /*** ID3DXConstantTable methods ***/
1465 ID3DXConstantTableImpl_GetDesc
,
1466 ID3DXConstantTableImpl_GetConstantDesc
,
1467 ID3DXConstantTableImpl_GetSamplerIndex
,
1468 ID3DXConstantTableImpl_GetConstant
,
1469 ID3DXConstantTableImpl_GetConstantByName
,
1470 ID3DXConstantTableImpl_GetConstantElement
,
1471 ID3DXConstantTableImpl_SetDefaults
,
1472 ID3DXConstantTableImpl_SetValue
,
1473 ID3DXConstantTableImpl_SetBool
,
1474 ID3DXConstantTableImpl_SetBoolArray
,
1475 ID3DXConstantTableImpl_SetInt
,
1476 ID3DXConstantTableImpl_SetIntArray
,
1477 ID3DXConstantTableImpl_SetFloat
,
1478 ID3DXConstantTableImpl_SetFloatArray
,
1479 ID3DXConstantTableImpl_SetVector
,
1480 ID3DXConstantTableImpl_SetVectorArray
,
1481 ID3DXConstantTableImpl_SetMatrix
,
1482 ID3DXConstantTableImpl_SetMatrixArray
,
1483 ID3DXConstantTableImpl_SetMatrixPointerArray
,
1484 ID3DXConstantTableImpl_SetMatrixTranspose
,
1485 ID3DXConstantTableImpl_SetMatrixTransposeArray
,
1486 ID3DXConstantTableImpl_SetMatrixTransposePointerArray
1489 static HRESULT
parse_ctab_constant_type(const char *ctab
, DWORD typeoffset
, struct ctab_constant
*constant
,
1490 BOOL is_element
, WORD index
, WORD max
, DWORD
*offset
, DWORD nameoffset
, UINT regset
)
1492 const D3DXSHADER_TYPEINFO
*type
= (LPD3DXSHADER_TYPEINFO
)(ctab
+ typeoffset
);
1493 const D3DXSHADER_STRUCTMEMBERINFO
*memberinfo
= NULL
;
1494 HRESULT hr
= D3D_OK
;
1498 constant
->desc
.DefaultValue
= offset
? ctab
+ *offset
: NULL
;
1499 constant
->desc
.Class
= type
->Class
;
1500 constant
->desc
.Type
= type
->Type
;
1501 constant
->desc
.Rows
= type
->Rows
;
1502 constant
->desc
.Columns
= type
->Columns
;
1503 constant
->desc
.Elements
= is_element
? 1 : type
->Elements
;
1504 constant
->desc
.StructMembers
= type
->StructMembers
;
1505 constant
->desc
.Name
= ctab
+ nameoffset
;
1506 constant
->desc
.RegisterSet
= regset
;
1507 constant
->desc
.RegisterIndex
= index
;
1509 TRACE("name %s, elements %u, index %u, defaultvalue %p, regset %s\n", constant
->desc
.Name
,
1510 constant
->desc
.Elements
, index
, constant
->desc
.DefaultValue
,
1511 debug_d3dxparameter_registerset(regset
));
1512 TRACE("class %s, type %s, rows %d, columns %d, elements %d, struct_members %d\n",
1513 debug_d3dxparameter_class(type
->Class
), debug_d3dxparameter_type(type
->Type
),
1514 type
->Rows
, type
->Columns
, type
->Elements
, type
->StructMembers
);
1516 if (type
->Elements
> 1 && !is_element
)
1518 count
= type
->Elements
;
1520 else if ((type
->Class
== D3DXPC_STRUCT
) && type
->StructMembers
)
1522 memberinfo
= (D3DXSHADER_STRUCTMEMBERINFO
*)(ctab
+ type
->StructMemberInfo
);
1523 count
= type
->StructMembers
;
1528 constant
->constants
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*constant
->constants
) * count
);
1529 if (!constant
->constants
)
1531 ERR("Out of memory\n");
1536 for (i
= 0; i
< count
; ++i
)
1538 hr
= parse_ctab_constant_type(ctab
, memberinfo
? memberinfo
[i
].TypeInfo
: typeoffset
,
1539 &constant
->constants
[i
], memberinfo
== NULL
, index
+ size
, max
, offset
,
1540 memberinfo
? memberinfo
[i
].Name
: nameoffset
, regset
);
1544 size
+= constant
->constants
[i
].desc
.RegisterCount
;
1549 WORD offsetdiff
= 0;
1551 switch (type
->Class
)
1559 case D3DXPC_MATRIX_ROWS
:
1560 size
= is_element
? type
->Rows
: max(type
->Rows
, type
->Columns
);
1561 offsetdiff
= type
->Rows
;
1564 case D3DXPC_MATRIX_COLUMNS
:
1565 size
= type
->Columns
;
1566 offsetdiff
= type
->Columns
;
1574 FIXME("Unhandled type class %s\n", debug_d3dxparameter_class(type
->Class
));
1578 /* offset in bytes => offsetdiff * components(4) * sizeof(DWORD) */
1579 if (offset
) *offset
+= offsetdiff
* 4 * 4;
1581 /* int and bool registerset have different sizes */
1582 if (regset
== D3DXRS_INT4
|| regset
== D3DXRS_BOOL
)
1584 switch (type
->Class
)
1588 size
= type
->Columns
;
1591 case D3DXPC_MATRIX_ROWS
:
1592 case D3DXPC_MATRIX_COLUMNS
:
1593 size
= 4 * type
->Columns
;
1597 FIXME("Unhandled type class %s\n", debug_d3dxparameter_class(type
->Class
));
1603 constant
->desc
.RegisterCount
= max(0, min(max
- index
, size
));
1604 constant
->desc
.Bytes
= 4 * constant
->desc
.Elements
* type
->Rows
* type
->Columns
;
1609 if (constant
->constants
)
1611 for (i
= 0; i
< count
; ++i
)
1613 free_constant(&constant
->constants
[i
]);
1615 HeapFree(GetProcessHeap(), 0, constant
->constants
);
1616 constant
->constants
= NULL
;
1622 HRESULT WINAPI
D3DXGetShaderConstantTableEx(const DWORD
*byte_code
, DWORD flags
, ID3DXConstantTable
**constant_table
)
1624 struct ID3DXConstantTableImpl
*object
= NULL
;
1628 const D3DXSHADER_CONSTANTTABLE
*ctab_header
;
1629 const D3DXSHADER_CONSTANTINFO
*constant_info
;
1632 TRACE("byte_code %p, flags %x, constant_table %p\n", byte_code
, flags
, constant_table
);
1634 if (constant_table
) *constant_table
= NULL
;
1636 if (!byte_code
|| !constant_table
)
1638 WARN("Invalid argument specified.\n");
1639 return D3DERR_INVALIDCALL
;
1642 if (!is_valid_bytecode(*byte_code
))
1644 WARN("Invalid byte_code specified.\n");
1648 if (flags
) FIXME("Flags (%#x) are not handled, yet!\n", flags
);
1650 hr
= D3DXFindShaderComment(byte_code
, MAKEFOURCC('C','T','A','B'), &data
, &size
);
1653 WARN("CTAB not found.\n");
1654 return D3DXERR_INVALIDDATA
;
1657 if (size
< sizeof(*ctab_header
))
1659 WARN("Invalid CTAB size.\n");
1660 return D3DXERR_INVALIDDATA
;
1663 ctab_header
= (const D3DXSHADER_CONSTANTTABLE
*)data
;
1664 if (ctab_header
->Size
!= sizeof(*ctab_header
))
1666 WARN("Invalid D3DXSHADER_CONSTANTTABLE size.\n");
1667 return D3DXERR_INVALIDDATA
;
1670 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1673 ERR("Out of memory\n");
1674 return E_OUTOFMEMORY
;
1677 object
->ID3DXConstantTable_iface
.lpVtbl
= &ID3DXConstantTable_Vtbl
;
1680 object
->ctab
= HeapAlloc(GetProcessHeap(), 0, size
);
1683 ERR("Out of memory\n");
1684 HeapFree(GetProcessHeap(), 0, object
);
1685 return E_OUTOFMEMORY
;
1687 object
->size
= size
;
1688 memcpy(object
->ctab
, data
, object
->size
);
1690 object
->desc
.Creator
= ctab_header
->Creator
? object
->ctab
+ ctab_header
->Creator
: NULL
;
1691 object
->desc
.Version
= ctab_header
->Version
;
1692 object
->desc
.Constants
= ctab_header
->Constants
;
1693 TRACE("Creator %s, Version %x, Constants %u, Target %s\n",
1694 debugstr_a(object
->desc
.Creator
), object
->desc
.Version
, object
->desc
.Constants
,
1695 debugstr_a(ctab_header
->Target
? object
->ctab
+ ctab_header
->Target
: NULL
));
1697 object
->constants
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1698 sizeof(*object
->constants
) * object
->desc
.Constants
);
1699 if (!object
->constants
)
1701 ERR("Out of memory\n");
1706 constant_info
= (const D3DXSHADER_CONSTANTINFO
*)(object
->ctab
+ ctab_header
->ConstantInfo
);
1707 for (i
= 0; i
< ctab_header
->Constants
; i
++)
1709 DWORD offset
= constant_info
[i
].DefaultValue
;
1711 hr
= parse_ctab_constant_type(object
->ctab
, constant_info
[i
].TypeInfo
,
1712 &object
->constants
[i
], FALSE
, constant_info
[i
].RegisterIndex
,
1713 constant_info
[i
].RegisterIndex
+ constant_info
[i
].RegisterCount
,
1714 offset
? &offset
: NULL
, constant_info
[i
].Name
, constant_info
[i
].RegisterSet
);
1719 *constant_table
= &object
->ID3DXConstantTable_iface
;
1724 free_constant_table(object
);
1725 HeapFree(GetProcessHeap(), 0, object
);
1730 HRESULT WINAPI
D3DXGetShaderConstantTable(const DWORD
*byte_code
, ID3DXConstantTable
**constant_table
)
1732 TRACE("(%p, %p): Forwarded to D3DXGetShaderConstantTableEx\n", byte_code
, constant_table
);
1734 return D3DXGetShaderConstantTableEx(byte_code
, 0, constant_table
);
1737 HRESULT WINAPI
D3DXGetShaderSamplers(const DWORD
*byte_code
, const char **samplers
, UINT
*count
)
1739 UINT i
, sampler_count
= 0;
1742 const D3DXSHADER_CONSTANTTABLE
*ctab_header
;
1743 const D3DXSHADER_CONSTANTINFO
*constant_info
;
1745 TRACE("byte_code %p, samplers %p, count %p\n", byte_code
, samplers
, count
);
1747 if (count
) *count
= 0;
1749 if (D3DXFindShaderComment(byte_code
, MAKEFOURCC('C','T','A','B'), (const void **)&data
, &size
) != D3D_OK
)
1752 if (size
< sizeof(*ctab_header
)) return D3D_OK
;
1754 ctab_header
= (const D3DXSHADER_CONSTANTTABLE
*)data
;
1755 if (ctab_header
->Size
!= sizeof(*ctab_header
)) return D3D_OK
;
1757 constant_info
= (const D3DXSHADER_CONSTANTINFO
*)(data
+ ctab_header
->ConstantInfo
);
1758 for (i
= 0; i
< ctab_header
->Constants
; i
++)
1760 const D3DXSHADER_TYPEINFO
*type
;
1762 TRACE("name = %s\n", data
+ constant_info
[i
].Name
);
1764 type
= (const D3DXSHADER_TYPEINFO
*)(data
+ constant_info
[i
].TypeInfo
);
1766 if (type
->Type
== D3DXPT_SAMPLER
1767 || type
->Type
== D3DXPT_SAMPLER1D
1768 || type
->Type
== D3DXPT_SAMPLER2D
1769 || type
->Type
== D3DXPT_SAMPLER3D
1770 || type
->Type
== D3DXPT_SAMPLERCUBE
)
1772 if (samplers
) samplers
[sampler_count
] = data
+ constant_info
[i
].Name
;
1778 TRACE("Found %u samplers\n", sampler_count
);
1780 if (count
) *count
= sampler_count
;