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
21 #include "d3dx9_36_private.h"
22 #include "d3dcompiler.h"
24 /* This function is not declared in the SDK headers yet */
25 HRESULT WINAPI
D3DAssemble(LPCVOID data
, SIZE_T datasize
, LPCSTR filename
,
26 const D3D_SHADER_MACRO
*defines
, ID3DInclude
*include
,
28 ID3DBlob
**shader
, ID3DBlob
**error_messages
);
30 static inline BOOL
is_valid_bytecode(DWORD token
)
32 return (token
& 0xfffe0000) == 0xfffe0000;
35 const char * WINAPI
D3DXGetPixelShaderProfile(struct IDirect3DDevice9
*device
)
39 TRACE("device %p\n", device
);
41 if (!device
) return NULL
;
43 IDirect3DDevice9_GetDeviceCaps(device
,&caps
);
45 switch (caps
.PixelShaderVersion
)
47 case D3DPS_VERSION(1, 1):
50 case D3DPS_VERSION(1, 2):
53 case D3DPS_VERSION(1, 3):
56 case D3DPS_VERSION(1, 4):
59 case D3DPS_VERSION(2, 0):
60 if ((caps
.PS20Caps
.NumTemps
>=22) &&
61 (caps
.PS20Caps
.Caps
&D3DPS20CAPS_ARBITRARYSWIZZLE
) &&
62 (caps
.PS20Caps
.Caps
&D3DPS20CAPS_GRADIENTINSTRUCTIONS
) &&
63 (caps
.PS20Caps
.Caps
&D3DPS20CAPS_PREDICATION
) &&
64 (caps
.PS20Caps
.Caps
&D3DPS20CAPS_NODEPENDENTREADLIMIT
) &&
65 (caps
.PS20Caps
.Caps
&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT
))
69 if ((caps
.PS20Caps
.NumTemps
>=32) &&
70 (caps
.PS20Caps
.Caps
&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT
))
76 case D3DPS_VERSION(3, 0):
83 UINT WINAPI
D3DXGetShaderSize(const DWORD
*byte_code
)
85 const DWORD
*ptr
= byte_code
;
87 TRACE("byte_code %p\n", byte_code
);
91 /* Look for the END token, skipping the VERSION token */
92 while (*++ptr
!= D3DSIO_END
)
95 if ((*ptr
& D3DSI_OPCODE_MASK
) == D3DSIO_COMMENT
)
97 ptr
+= ((*ptr
& D3DSI_COMMENTSIZE_MASK
) >> D3DSI_COMMENTSIZE_SHIFT
);
102 /* Return the shader size in bytes */
103 return (ptr
- byte_code
) * sizeof(*ptr
);
106 DWORD WINAPI
D3DXGetShaderVersion(const DWORD
*byte_code
)
108 TRACE("byte_code %p\n", byte_code
);
110 return byte_code
? *byte_code
: 0;
113 const char * WINAPI
D3DXGetVertexShaderProfile(struct IDirect3DDevice9
*device
)
117 TRACE("device %p\n", device
);
119 if (!device
) return NULL
;
121 IDirect3DDevice9_GetDeviceCaps(device
,&caps
);
123 switch (caps
.VertexShaderVersion
)
125 case D3DVS_VERSION(1, 1):
127 case D3DVS_VERSION(2, 0):
128 if ((caps
.VS20Caps
.NumTemps
>=13) &&
129 (caps
.VS20Caps
.DynamicFlowControlDepth
==24) &&
130 (caps
.VS20Caps
.Caps
&D3DPS20CAPS_PREDICATION
))
135 case D3DVS_VERSION(3, 0):
142 HRESULT WINAPI
D3DXFindShaderComment(const DWORD
*byte_code
, DWORD fourcc
, const void **data
, UINT
*size
)
144 const DWORD
*ptr
= byte_code
;
146 TRACE("byte_code %p, fourcc %x, data %p, size %p\n", byte_code
, fourcc
, data
, size
);
148 if (data
) *data
= NULL
;
151 if (!byte_code
) return D3DERR_INVALIDCALL
;
152 if (!is_valid_bytecode(*byte_code
)) return D3DXERR_INVALIDDATA
;
154 while (*++ptr
!= D3DSIO_END
)
156 /* Check if it is a comment */
157 if ((*ptr
& D3DSI_OPCODE_MASK
) == D3DSIO_COMMENT
)
159 DWORD comment_size
= (*ptr
& D3DSI_COMMENTSIZE_MASK
) >> D3DSI_COMMENTSIZE_SHIFT
;
161 /* Check if this is the comment we are looking for */
162 if (*(ptr
+ 1) == fourcc
)
164 UINT ctab_size
= (comment_size
- 1) * sizeof(DWORD
);
165 LPCVOID ctab_data
= ptr
+ 2;
170 TRACE("Returning comment data at %p with size %d\n", ctab_data
, ctab_size
);
180 HRESULT WINAPI
D3DXAssembleShader(const char *data
, UINT data_len
, const D3DXMACRO
*defines
,
181 ID3DXInclude
*include
, DWORD flags
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
185 TRACE("data %p, data_len %u, defines %p, include %p, flags %#x, shader %p, error_messages %p\n",
186 data
, data_len
, defines
, include
, flags
, shader
, error_messages
);
188 /* Forward to d3dcompiler: the parameter types aren't really different,
189 the actual data types are equivalent */
190 hr
= D3DAssemble(data
, data_len
, NULL
, (D3D_SHADER_MACRO
*)defines
,
191 (ID3DInclude
*)include
, flags
, (ID3DBlob
**)shader
,
192 (ID3DBlob
**)error_messages
);
194 if(hr
== E_FAIL
) hr
= D3DXERR_INVALIDDATA
;
198 /* D3DXInclude private implementation, used to implement
199 D3DXAssembleShaderFromFile from D3DXAssembleShader */
200 /* To be able to correctly resolve include search paths we have to store
201 the pathname of each include file. We store the pathname pointer right
202 before the file data. */
203 static HRESULT WINAPI
d3dincludefromfile_open(ID3DXInclude
*iface
,
204 D3DXINCLUDE_TYPE include_type
,
205 LPCSTR filename
, LPCVOID parent_data
,
206 LPCVOID
*data
, UINT
*bytes
) {
207 const char *p
, *parent_name
= "";
208 char *pathname
= NULL
;
209 char **buffer
= NULL
;
213 if(parent_data
!= NULL
)
214 parent_name
= *((const char **)parent_data
- 1);
216 TRACE("Looking up for include file %s, parent %s\n", debugstr_a(filename
), debugstr_a(parent_name
));
218 if ((p
= strrchr(parent_name
, '\\')) || (p
= strrchr(parent_name
, '/'))) p
++;
219 else p
= parent_name
;
220 pathname
= HeapAlloc(GetProcessHeap(), 0, (p
- parent_name
) + strlen(filename
) + 1);
222 return HRESULT_FROM_WIN32(GetLastError());
224 memcpy(pathname
, parent_name
, p
- parent_name
);
225 strcpy(pathname
+ (p
- parent_name
), filename
);
227 file
= CreateFileA(pathname
, GENERIC_READ
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
228 if(file
== INVALID_HANDLE_VALUE
)
231 TRACE("Include file found at pathname = %s\n", debugstr_a(pathname
));
233 size
= GetFileSize(file
, NULL
);
234 if(size
== INVALID_FILE_SIZE
)
237 buffer
= HeapAlloc(GetProcessHeap(), 0, size
+ sizeof(char *));
241 if(!ReadFile(file
, buffer
+ 1, size
, bytes
, NULL
))
251 HeapFree(GetProcessHeap(), 0, pathname
);
252 HeapFree(GetProcessHeap(), 0, buffer
);
253 return HRESULT_FROM_WIN32(GetLastError());
256 static HRESULT WINAPI
d3dincludefromfile_close(ID3DXInclude
*iface
, LPCVOID data
) {
257 HeapFree(GetProcessHeap(), 0, *((char **)data
- 1));
258 HeapFree(GetProcessHeap(), 0, (char **)data
- 1);
262 static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl
= {
263 d3dincludefromfile_open
,
264 d3dincludefromfile_close
267 struct D3DXIncludeImpl
{
268 ID3DXInclude ID3DXInclude_iface
;
271 HRESULT WINAPI
D3DXAssembleShaderFromFileA(const char *filename
, const D3DXMACRO
*defines
,
272 ID3DXInclude
*include
, DWORD flags
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
274 LPWSTR filename_w
= NULL
;
278 if (!filename
) return D3DXERR_INVALIDDATA
;
280 len
= MultiByteToWideChar(CP_ACP
, 0, filename
, -1, NULL
, 0);
281 filename_w
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
282 if (!filename_w
) return E_OUTOFMEMORY
;
283 MultiByteToWideChar(CP_ACP
, 0, filename
, -1, filename_w
, len
);
285 ret
= D3DXAssembleShaderFromFileW(filename_w
, defines
, include
, flags
, shader
, error_messages
);
287 HeapFree(GetProcessHeap(), 0, filename_w
);
291 HRESULT WINAPI
D3DXAssembleShaderFromFileW(const WCHAR
*filename
, const D3DXMACRO
*defines
,
292 ID3DXInclude
*include
, DWORD flags
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
297 struct D3DXIncludeImpl includefromfile
;
299 if(FAILED(map_view_of_file(filename
, &buffer
, &len
)))
300 return D3DXERR_INVALIDDATA
;
304 includefromfile
.ID3DXInclude_iface
.lpVtbl
= &D3DXInclude_Vtbl
;
305 include
= &includefromfile
.ID3DXInclude_iface
;
308 hr
= D3DXAssembleShader(buffer
, len
, defines
, include
, flags
,
309 shader
, error_messages
);
311 UnmapViewOfFile(buffer
);
315 HRESULT WINAPI
D3DXAssembleShaderFromResourceA(HMODULE module
, const char *resource
, const D3DXMACRO
*defines
,
316 ID3DXInclude
*include
, DWORD flags
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
322 if (!(res
= FindResourceA(module
, resource
, (LPCSTR
)RT_RCDATA
)))
323 return D3DXERR_INVALIDDATA
;
324 if (FAILED(load_resource_into_memory(module
, res
, &buffer
, &len
)))
325 return D3DXERR_INVALIDDATA
;
326 return D3DXAssembleShader(buffer
, len
, defines
, include
, flags
,
327 shader
, error_messages
);
330 HRESULT WINAPI
D3DXAssembleShaderFromResourceW(HMODULE module
, const WCHAR
*resource
, const D3DXMACRO
*defines
,
331 ID3DXInclude
*include
, DWORD flags
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
337 TRACE("module %p, resource %s, defines %p, include %p, flags %#x, shader %p, error_messages %p.\n",
338 module
, debugstr_w(resource
), defines
, include
, flags
, shader
, error_messages
);
340 if (!(res
= FindResourceW(module
, resource
, (const WCHAR
*)RT_RCDATA
)))
341 return D3DXERR_INVALIDDATA
;
342 if (FAILED(load_resource_into_memory(module
, res
, &buffer
, &len
)))
343 return D3DXERR_INVALIDDATA
;
344 return D3DXAssembleShader(buffer
, len
, defines
, include
, flags
,
345 shader
, error_messages
);
348 HRESULT WINAPI
D3DXCompileShader(const char *data
, UINT length
, const D3DXMACRO
*defines
,
349 ID3DXInclude
*include
, const char *function
, const char *profile
, DWORD flags
,
350 ID3DXBuffer
**shader
, ID3DXBuffer
**error_msgs
, ID3DXConstantTable
**constant_table
)
354 TRACE("data %p, length %u, defines %p, include %p, function %s, profile %s, flags %#x, shader %p, error_msgs %p, constant_table %p\n",
355 data
, length
, defines
, include
, function
, profile
, flags
, shader
, error_msgs
, constant_table
);
357 hr
= D3DCompile(data
, length
, NULL
, (D3D_SHADER_MACRO
*)defines
, (ID3DInclude
*)include
,
358 function
, profile
, flags
, 0, (ID3DBlob
**)shader
, (ID3DBlob
**)error_msgs
);
360 if (SUCCEEDED(hr
) && constant_table
)
362 hr
= D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader
), constant_table
);
365 ID3DXBuffer_Release(*shader
);
373 HRESULT WINAPI
D3DXCompileShaderFromFileA(const char *filename
, const D3DXMACRO
*defines
,
374 ID3DXInclude
*include
, const char *entrypoint
, const char *profile
, DWORD flags
,
375 ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
, ID3DXConstantTable
**constant_table
)
377 LPWSTR filename_w
= NULL
;
381 if (!filename
) return D3DXERR_INVALIDDATA
;
383 len
= MultiByteToWideChar(CP_ACP
, 0, filename
, -1, NULL
, 0);
384 filename_w
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
385 if (!filename_w
) return E_OUTOFMEMORY
;
386 MultiByteToWideChar(CP_ACP
, 0, filename
, -1, filename_w
, len
);
388 ret
= D3DXCompileShaderFromFileW(filename_w
, defines
, include
,
389 entrypoint
, profile
, flags
,
390 shader
, error_messages
, constant_table
);
392 HeapFree(GetProcessHeap(), 0, filename_w
);
396 HRESULT WINAPI
D3DXCompileShaderFromFileW(const WCHAR
*filename
, const D3DXMACRO
*defines
,
397 ID3DXInclude
*include
, const char *entrypoint
, const char *profile
, DWORD flags
,
398 ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
, ID3DXConstantTable
**constant_table
)
401 DWORD len
, filename_len
;
403 struct D3DXIncludeImpl includefromfile
;
406 if (FAILED(map_view_of_file(filename
, &buffer
, &len
)))
407 return D3DXERR_INVALIDDATA
;
411 includefromfile
.ID3DXInclude_iface
.lpVtbl
= &D3DXInclude_Vtbl
;
412 include
= &includefromfile
.ID3DXInclude_iface
;
415 filename_len
= WideCharToMultiByte(CP_ACP
, 0, filename
, -1, NULL
, 0, NULL
, NULL
);
416 filename_a
= HeapAlloc(GetProcessHeap(), 0, filename_len
* sizeof(char));
419 UnmapViewOfFile(buffer
);
420 return E_OUTOFMEMORY
;
422 WideCharToMultiByte(CP_ACP
, 0, filename
, -1, filename_a
, filename_len
, NULL
, NULL
);
424 hr
= D3DCompile(buffer
, len
, filename_a
, (const D3D_SHADER_MACRO
*)defines
,
425 (ID3DInclude
*)include
, entrypoint
, profile
, flags
, 0,
426 (ID3DBlob
**)shader
, (ID3DBlob
**)error_messages
);
428 if (SUCCEEDED(hr
) && constant_table
)
429 hr
= D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader
),
432 HeapFree(GetProcessHeap(), 0, filename_a
);
433 UnmapViewOfFile(buffer
);
437 HRESULT WINAPI
D3DXCompileShaderFromResourceA(HMODULE module
, const char *resource
, const D3DXMACRO
*defines
,
438 ID3DXInclude
*include
, const char *entrypoint
, const char *profile
, DWORD flags
,
439 ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
, ID3DXConstantTable
**constant_table
)
445 if (!(res
= FindResourceA(module
, resource
, (LPCSTR
)RT_RCDATA
)))
446 return D3DXERR_INVALIDDATA
;
447 if (FAILED(load_resource_into_memory(module
, res
, &buffer
, &len
)))
448 return D3DXERR_INVALIDDATA
;
449 return D3DXCompileShader(buffer
, len
, defines
, include
, entrypoint
, profile
,
450 flags
, shader
, error_messages
, constant_table
);
453 HRESULT WINAPI
D3DXCompileShaderFromResourceW(HMODULE module
, const WCHAR
*resource
, const D3DXMACRO
*defines
,
454 ID3DXInclude
*include
, const char *entrypoint
, const char *profile
, DWORD flags
,
455 ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
, ID3DXConstantTable
**constant_table
)
461 TRACE("module %p, resource %s, defines %p, include %p, entrypoint %s, profile %s, "
462 "flags %#x, shader %p, error_messages %p, constant_table %p.\n",
463 module
, debugstr_w(resource
), defines
, include
, debugstr_a(entrypoint
), debugstr_a(profile
),
464 flags
, shader
, error_messages
, constant_table
);
466 if (!(res
= FindResourceW(module
, resource
, (const WCHAR
*)RT_RCDATA
)))
467 return D3DXERR_INVALIDDATA
;
468 if (FAILED(load_resource_into_memory(module
, res
, &buffer
, &len
)))
469 return D3DXERR_INVALIDDATA
;
470 return D3DXCompileShader(buffer
, len
, defines
, include
, entrypoint
, profile
,
471 flags
, shader
, error_messages
, constant_table
);
474 HRESULT WINAPI
D3DXPreprocessShader(const char *data
, UINT data_len
, const D3DXMACRO
*defines
,
475 ID3DXInclude
*include
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
477 TRACE("Forward to D3DPreprocess\n");
478 return D3DPreprocess(data
, data_len
, NULL
,
479 (const D3D_SHADER_MACRO
*)defines
, (ID3DInclude
*)include
,
480 (ID3DBlob
**)shader
, (ID3DBlob
**)error_messages
);
483 HRESULT WINAPI
D3DXPreprocessShaderFromFileA(const char *filename
, const D3DXMACRO
*defines
,
484 ID3DXInclude
*include
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
486 WCHAR
*filename_w
= NULL
;
490 if (!filename
) return D3DXERR_INVALIDDATA
;
492 len
= MultiByteToWideChar(CP_ACP
, 0, filename
, -1, NULL
, 0);
493 filename_w
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
494 if (!filename_w
) return E_OUTOFMEMORY
;
495 MultiByteToWideChar(CP_ACP
, 0, filename
, -1, filename_w
, len
);
497 ret
= D3DXPreprocessShaderFromFileW(filename_w
, defines
, include
, shader
, error_messages
);
499 HeapFree(GetProcessHeap(), 0, filename_w
);
503 HRESULT WINAPI
D3DXPreprocessShaderFromFileW(const WCHAR
*filename
, const D3DXMACRO
*defines
,
504 ID3DXInclude
*include
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
509 struct D3DXIncludeImpl includefromfile
;
511 if (FAILED(map_view_of_file(filename
, &buffer
, &len
)))
512 return D3DXERR_INVALIDDATA
;
516 includefromfile
.ID3DXInclude_iface
.lpVtbl
= &D3DXInclude_Vtbl
;
517 include
= &includefromfile
.ID3DXInclude_iface
;
520 hr
= D3DPreprocess(buffer
, len
, NULL
,
521 (const D3D_SHADER_MACRO
*)defines
,
522 (ID3DInclude
*) include
,
523 (ID3DBlob
**)shader
, (ID3DBlob
**)error_messages
);
525 UnmapViewOfFile(buffer
);
529 HRESULT WINAPI
D3DXPreprocessShaderFromResourceA(HMODULE module
, const char *resource
, const D3DXMACRO
*defines
,
530 ID3DXInclude
*include
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
536 if (!(res
= FindResourceA(module
, resource
, (LPCSTR
)RT_RCDATA
)))
537 return D3DXERR_INVALIDDATA
;
538 if (FAILED(load_resource_into_memory(module
, res
, &buffer
, &len
)))
539 return D3DXERR_INVALIDDATA
;
540 return D3DXPreprocessShader(buffer
, len
, defines
, include
,
541 shader
, error_messages
);
544 HRESULT WINAPI
D3DXPreprocessShaderFromResourceW(HMODULE module
, const WCHAR
*resource
, const D3DXMACRO
*defines
,
545 ID3DXInclude
*include
, ID3DXBuffer
**shader
, ID3DXBuffer
**error_messages
)
551 if (!(res
= FindResourceW(module
, resource
, (const WCHAR
*)RT_RCDATA
)))
552 return D3DXERR_INVALIDDATA
;
553 if (FAILED(load_resource_into_memory(module
, res
, &buffer
, &len
)))
554 return D3DXERR_INVALIDDATA
;
555 return D3DXPreprocessShader(buffer
, len
, defines
, include
,
556 shader
, error_messages
);
560 struct ctab_constant
{
561 D3DXCONSTANT_DESC desc
;
562 struct ctab_constant
*constants
;
565 struct ID3DXConstantTableImpl
{
566 ID3DXConstantTable ID3DXConstantTable_iface
;
570 D3DXCONSTANTTABLE_DESC desc
;
571 struct ctab_constant
*constants
;
574 static void free_constant(struct ctab_constant
*constant
)
576 if (constant
->constants
)
578 UINT i
, count
= constant
->desc
.Elements
> 1 ? constant
->desc
.Elements
: constant
->desc
.StructMembers
;
580 for (i
= 0; i
< count
; ++i
)
582 free_constant(&constant
->constants
[i
]);
584 HeapFree(GetProcessHeap(), 0, constant
->constants
);
588 static void free_constant_table(struct ID3DXConstantTableImpl
*table
)
590 if (table
->constants
)
594 for (i
= 0; i
< table
->desc
.Constants
; ++i
)
596 free_constant(&table
->constants
[i
]);
598 HeapFree(GetProcessHeap(), 0, table
->constants
);
600 HeapFree(GetProcessHeap(), 0, table
->ctab
);
603 static inline struct ID3DXConstantTableImpl
*impl_from_ID3DXConstantTable(ID3DXConstantTable
*iface
)
605 return CONTAINING_RECORD(iface
, struct ID3DXConstantTableImpl
, ID3DXConstantTable_iface
);
608 static inline BOOL
is_vertex_shader(DWORD version
)
610 return (version
& 0xffff0000) == 0xfffe0000;
613 static inline D3DXHANDLE
handle_from_constant(struct ctab_constant
*constant
)
615 return (D3DXHANDLE
)constant
;
618 static struct ctab_constant
*get_constant_by_name(struct ID3DXConstantTableImpl
*, struct ctab_constant
*, LPCSTR
);
620 static struct ctab_constant
*get_constant_element_by_name(struct ctab_constant
*constant
, LPCSTR name
)
625 TRACE("constant %p, name %s\n", constant
, debugstr_a(name
));
627 if (!name
|| !*name
) return NULL
;
629 element
= atoi(name
);
630 part
= strchr(name
, ']') + 1;
632 if (constant
->desc
.Elements
> element
)
634 struct ctab_constant
*c
= constant
->constants
? &constant
->constants
[element
] : constant
;
639 return get_constant_by_name(NULL
, c
, part
);
642 return get_constant_element_by_name(c
, part
);
645 TRACE("Returning parameter %p\n", c
);
649 FIXME("Unhandled case \"%c\"\n", *--part
);
654 TRACE("Constant not found\n");
658 static struct ctab_constant
*get_constant_by_name(struct ID3DXConstantTableImpl
*table
,
659 struct ctab_constant
*constant
, LPCSTR name
)
661 UINT i
, count
, length
;
662 struct ctab_constant
*handles
;
665 TRACE("table %p, constant %p, name %s\n", table
, constant
, debugstr_a(name
));
667 if (!name
|| !*name
) return NULL
;
671 count
= table
->desc
.Constants
;
672 handles
= table
->constants
;
676 count
= constant
->desc
.StructMembers
;
677 handles
= constant
->constants
;
680 length
= strcspn(name
, "[.");
681 part
= name
+ length
;
683 for (i
= 0; i
< count
; i
++)
685 if (strlen(handles
[i
].desc
.Name
) == length
&& !strncmp(handles
[i
].desc
.Name
, name
, length
))
690 return get_constant_by_name(NULL
, &handles
[i
], part
);
693 return get_constant_element_by_name(&handles
[i
], part
);
696 TRACE("Returning parameter %p\n", &handles
[i
]);
702 TRACE("Constant not found\n");
706 static struct ctab_constant
*is_valid_sub_constant(struct ctab_constant
*parent
, D3DXHANDLE handle
)
708 struct ctab_constant
*c
;
711 /* all variable have at least elements = 1, but not always elements */
712 if (!parent
->constants
) return NULL
;
714 count
= parent
->desc
.Elements
> 1 ? parent
->desc
.Elements
: parent
->desc
.StructMembers
;
715 for (i
= 0; i
< count
; ++i
)
717 if (handle_from_constant(&parent
->constants
[i
]) == handle
)
718 return &parent
->constants
[i
];
720 c
= is_valid_sub_constant(&parent
->constants
[i
], handle
);
727 static inline struct ctab_constant
*get_valid_constant(struct ID3DXConstantTableImpl
*table
, D3DXHANDLE handle
)
729 struct ctab_constant
*c
;
732 if (!handle
) return NULL
;
734 for (i
= 0; i
< table
->desc
.Constants
; ++i
)
736 if (handle_from_constant(&table
->constants
[i
]) == handle
)
737 return &table
->constants
[i
];
739 c
= is_valid_sub_constant(&table
->constants
[i
], handle
);
743 return get_constant_by_name(table
, NULL
, handle
);
746 /*** IUnknown methods ***/
747 static HRESULT WINAPI
ID3DXConstantTableImpl_QueryInterface(ID3DXConstantTable
*iface
, REFIID riid
, void **out
)
749 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
751 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
752 IsEqualGUID(riid
, &IID_ID3DXBuffer
) ||
753 IsEqualGUID(riid
, &IID_ID3DXConstantTable
))
755 ID3DXConstantTable_AddRef(iface
);
760 WARN("Interface %s not found.\n", debugstr_guid(riid
));
762 return E_NOINTERFACE
;
765 static ULONG WINAPI
ID3DXConstantTableImpl_AddRef(ID3DXConstantTable
*iface
)
767 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
769 TRACE("(%p)->(): AddRef from %d\n", This
, This
->ref
);
771 return InterlockedIncrement(&This
->ref
);
774 static ULONG WINAPI
ID3DXConstantTableImpl_Release(ID3DXConstantTable
*iface
)
776 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
777 ULONG ref
= InterlockedDecrement(&This
->ref
);
779 TRACE("(%p)->(): Release from %d\n", This
, ref
+ 1);
783 free_constant_table(This
);
784 HeapFree(GetProcessHeap(), 0, This
);
790 /*** ID3DXBuffer methods ***/
791 static LPVOID WINAPI
ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable
*iface
)
793 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
795 TRACE("(%p)->()\n", This
);
800 static DWORD WINAPI
ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable
*iface
)
802 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
804 TRACE("(%p)->()\n", This
);
809 /*** ID3DXConstantTable methods ***/
810 static HRESULT WINAPI
ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable
*iface
, D3DXCONSTANTTABLE_DESC
*desc
)
812 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
814 TRACE("(%p)->(%p)\n", This
, desc
);
817 return D3DERR_INVALIDCALL
;
824 static HRESULT WINAPI
ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable
*iface
, D3DXHANDLE constant
,
825 D3DXCONSTANT_DESC
*desc
, UINT
*count
)
827 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
828 struct ctab_constant
*c
= get_valid_constant(This
, constant
);
830 TRACE("(%p)->(%p, %p, %p)\n", This
, constant
, desc
, count
);
834 WARN("Invalid argument specified\n");
835 return D3DERR_INVALIDCALL
;
838 if (desc
) *desc
= c
->desc
;
839 if (count
) *count
= 1;
844 static UINT WINAPI
ID3DXConstantTableImpl_GetSamplerIndex(ID3DXConstantTable
*iface
, D3DXHANDLE constant
)
846 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
847 struct ctab_constant
*c
= get_valid_constant(This
, constant
);
849 TRACE("(%p)->(%p)\n", This
, constant
);
851 if (!c
|| c
->desc
.RegisterSet
!= D3DXRS_SAMPLER
)
853 WARN("Invalid argument specified\n");
857 TRACE("Returning RegisterIndex %u\n", c
->desc
.RegisterIndex
);
858 return c
->desc
.RegisterIndex
;
861 static D3DXHANDLE WINAPI
ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable
*iface
, D3DXHANDLE constant
, UINT index
)
863 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
864 struct ctab_constant
*c
;
866 TRACE("(%p)->(%p, %d)\n", This
, constant
, index
);
870 c
= get_valid_constant(This
, constant
);
871 if (c
&& index
< c
->desc
.StructMembers
)
873 c
= &c
->constants
[index
];
874 TRACE("Returning constant %p\n", c
);
875 return handle_from_constant(c
);
880 if (index
< This
->desc
.Constants
)
882 c
= &This
->constants
[index
];
883 TRACE("Returning constant %p\n", c
);
884 return handle_from_constant(c
);
888 WARN("Index out of range\n");
892 static D3DXHANDLE WINAPI
ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable
*iface
, D3DXHANDLE constant
, LPCSTR name
)
894 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
895 struct ctab_constant
*c
= get_valid_constant(This
, constant
);
897 TRACE("(%p)->(%p, %s)\n", This
, constant
, name
);
899 c
= get_constant_by_name(This
, c
, name
);
900 TRACE("Returning constant %p\n", c
);
902 return handle_from_constant(c
);
905 static D3DXHANDLE WINAPI
ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable
*iface
, D3DXHANDLE constant
, UINT index
)
907 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
908 struct ctab_constant
*c
= get_valid_constant(This
, constant
);
910 TRACE("(%p)->(%p, %d)\n", This
, constant
, index
);
912 if (c
&& index
< c
->desc
.Elements
)
914 if (c
->desc
.Elements
> 1) c
= &c
->constants
[index
];
915 TRACE("Returning constant %p\n", c
);
916 return handle_from_constant(c
);
919 WARN("Invalid argument specified\n");
923 static inline DWORD
get_index(const void **indata
, UINT index
, BOOL is_pointer
)
929 return ((DWORD
**)indata
)[index
/ 16][index
% 16];
931 return (*((DWORD
**)indata
))[index
];
934 static UINT
set(struct ID3DXConstantTableImpl
*table
, IDirect3DDevice9
*device
, struct ctab_constant
*constant
,
935 const void **indata
, D3DXPARAMETER_TYPE intype
, UINT
*size
, UINT incol
, D3DXPARAMETER_CLASS inclass
, UINT index
,
938 D3DXCONSTANT_DESC
*desc
= &constant
->desc
;
939 UINT l
, i
, regcount
= 1, regsize
= 1, cin
= 1, rin
= 1, ret
, last
= 0;
942 /* size to small to set anything */
943 if (*size
< desc
->Rows
* desc
->Columns
)
949 /* D3DXPC_STRUCT is somewhat special */
950 if (desc
->Class
== D3DXPC_STRUCT
)
953 * Struct array sets the last complete input to the first struct element, all other
954 * elements are not set.
955 * E.g.: struct {int i;} s1[2];
956 * SetValue(device, "s1", [1, 2], 8) => s1 = {2, x};
958 * struct {int i; int n} s2[2];
959 * SetValue(device, "s2", [1, 2, 3, 4, 5], 20) => s1 = {{3, 4}, {x, x}};
961 if (desc
->Elements
> 1)
963 UINT offset
= *size
/ (desc
->Rows
* desc
->Columns
) - 1;
965 offset
= min(desc
->Elements
- 1, offset
);
966 last
= offset
* desc
->Rows
* desc
->Columns
;
968 if ((is_pointer
|| (!is_pointer
&& inclass
== D3DXPC_MATRIX_ROWS
)) && desc
->RegisterSet
!= D3DXRS_BOOL
)
970 set(table
, device
, &constant
->constants
[0], NULL
, intype
, size
, incol
, inclass
, 0, is_pointer
);
974 last
+= set(table
, device
, &constant
->constants
[0], indata
, intype
, size
, incol
, inclass
,
975 index
+ last
, is_pointer
);
981 * D3DXRS_BOOL is always set. As there are only 16 bools and there are
982 * exactly 16 input values, use matrix transpose.
984 if (inclass
== D3DXPC_MATRIX_ROWS
&& desc
->RegisterSet
== D3DXRS_BOOL
)
986 D3DXMATRIX mat
, *m
, min
;
987 D3DXMatrixTranspose(&mat
, &min
);
990 min
= *(D3DXMATRIX
*)(indata
[index
/ 16]);
992 min
= **(D3DXMATRIX
**)indata
;
994 D3DXMatrixTranspose(&mat
, &min
);
996 for (i
= 0; i
< desc
->StructMembers
; ++i
)
998 last
+= set(table
, device
, &constant
->constants
[i
], (const void **)&m
, intype
, size
, incol
,
999 D3DXPC_SCALAR
, index
+ last
, is_pointer
);
1003 * For pointers or for matrix rows, only the first member is set.
1004 * All other members are set to 0. This is not true for D3DXRS_BOOL.
1005 * E.g.: struct {int i; int n} s;
1006 * SetValue(device, "s", [1, 2], 8) => s = {1, 0};
1008 else if ((is_pointer
|| (!is_pointer
&& inclass
== D3DXPC_MATRIX_ROWS
)) && desc
->RegisterSet
!= D3DXRS_BOOL
)
1010 last
= set(table
, device
, &constant
->constants
[0], indata
, intype
, size
, incol
, inclass
,
1011 index
+ last
, is_pointer
);
1013 for (i
= 1; i
< desc
->StructMembers
; ++i
)
1015 set(table
, device
, &constant
->constants
[i
], NULL
, intype
, size
, incol
, inclass
, 0, is_pointer
);
1020 for (i
= 0; i
< desc
->StructMembers
; ++i
)
1022 last
+= set(table
, device
, &constant
->constants
[i
], indata
, intype
, size
, incol
, D3DXPC_SCALAR
,
1023 index
+ last
, is_pointer
);
1032 if (desc
->Elements
> 1)
1034 for (i
= 0; i
< desc
->Elements
&& *size
> 0; ++i
)
1036 last
+= set(table
, device
, &constant
->constants
[i
], indata
, intype
, size
, incol
, inclass
,
1037 index
+ last
, is_pointer
);
1039 /* adjust the vector size for matrix rows */
1040 if (inclass
== D3DXPC_MATRIX_ROWS
&& desc
->Class
== D3DXPC_VECTOR
&& (i
% 4) == 3)
1043 *size
= *size
< 12 ? 0 : *size
- 12;
1050 switch (desc
->Class
)
1054 case D3DXPC_MATRIX_ROWS
:
1055 regcount
= min(desc
->RegisterCount
, desc
->Rows
);
1056 if (inclass
== D3DXPC_MATRIX_ROWS
) cin
= incol
;
1058 regsize
= desc
->Columns
;
1061 case D3DXPC_MATRIX_COLUMNS
:
1062 regcount
= desc
->Columns
;
1063 if (inclass
== D3DXPC_MATRIX_ROWS
) rin
= incol
;
1065 regsize
= desc
->Rows
;
1069 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc
->Class
));
1073 /* specific stuff for different in types */
1077 ret
= desc
->Columns
* desc
->Rows
;
1078 *size
-= desc
->Columns
* desc
->Rows
;
1082 switch (desc
->Class
)
1084 case D3DXPC_MATRIX_ROWS
:
1085 if (*size
< regcount
* 4)
1091 *size
-= 4 * regcount
;
1094 case D3DXPC_MATRIX_COLUMNS
:
1096 *size
-= 4 * regcount
;
1110 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc
->Class
));
1115 case D3DXPC_MATRIX_ROWS
:
1116 switch (desc
->Class
)
1118 case D3DXPC_MATRIX_ROWS
:
1119 case D3DXPC_MATRIX_COLUMNS
:
1137 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc
->Class
));
1143 case D3DXPC_MATRIX_COLUMNS
:
1144 switch (desc
->Class
)
1146 case D3DXPC_MATRIX_ROWS
:
1147 case D3DXPC_MATRIX_COLUMNS
:
1165 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc
->Class
));
1172 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(inclass
));
1176 /* set the registers */
1177 switch (desc
->RegisterSet
)
1180 regcount
= min(desc
->RegisterCount
, desc
->Columns
* desc
->Rows
);
1182 for (i
= 0; i
< regcount
; ++i
)
1185 DWORD t
= get_index(indata
, index
+ i
/ regsize
* rin
+ l
* cin
, is_pointer
);
1187 set_number(&tmp
, desc
->Type
, &t
, intype
);
1188 set_number(&out
, D3DXPT_BOOL
, &tmp
, desc
->Type
);
1189 if (is_vertex_shader(table
->desc
.Version
))
1190 IDirect3DDevice9_SetVertexShaderConstantB(device
, desc
->RegisterIndex
+ i
, &out
, 1);
1192 IDirect3DDevice9_SetPixelShaderConstantB(device
, desc
->RegisterIndex
+ i
, &out
, 1);
1194 if (++l
>= regsize
) l
= 0;
1199 for (i
= 0; i
< regcount
; ++i
)
1201 INT vec
[4] = {0, 0, 1, 0};
1203 for (l
= 0; l
< regsize
; ++l
)
1205 DWORD t
= get_index(indata
, index
+ i
* rin
+ l
* cin
, is_pointer
);
1207 set_number(&tmp
, desc
->Type
, &t
, intype
);
1208 set_number(&vec
[l
], D3DXPT_INT
, &tmp
, desc
->Type
);
1210 if (is_vertex_shader(table
->desc
.Version
))
1211 IDirect3DDevice9_SetVertexShaderConstantI(device
, desc
->RegisterIndex
+ i
, vec
, 1);
1213 IDirect3DDevice9_SetPixelShaderConstantI(device
, desc
->RegisterIndex
+ i
, vec
, 1);
1218 for (i
= 0; i
< regcount
; ++i
)
1222 for (l
= 0; l
< regsize
; ++l
)
1224 DWORD t
= get_index(indata
, index
+ i
* rin
+ l
* cin
, is_pointer
);
1226 set_number(&tmp
, desc
->Type
, &t
, intype
);
1227 set_number(&vec
[l
], D3DXPT_FLOAT
, &tmp
, desc
->Type
);
1229 if (is_vertex_shader(table
->desc
.Version
))
1230 IDirect3DDevice9_SetVertexShaderConstantF(device
, desc
->RegisterIndex
+ i
, vec
, 1);
1232 IDirect3DDevice9_SetPixelShaderConstantF(device
, desc
->RegisterIndex
+ i
, vec
, 1);
1237 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc
->RegisterSet
));
1242 static HRESULT
set_scalar(struct ID3DXConstantTableImpl
*table
, IDirect3DDevice9
*device
, D3DXHANDLE constant
,
1243 const void *indata
, D3DXPARAMETER_TYPE intype
)
1245 struct ctab_constant
*c
= get_valid_constant(table
, constant
);
1250 WARN("Invalid argument specified\n");
1251 return D3DERR_INVALIDCALL
;
1254 switch (c
->desc
.Class
)
1257 set(table
, device
, c
, &indata
, intype
, &count
, c
->desc
.Columns
, D3DXPC_SCALAR
, 0, FALSE
);
1261 case D3DXPC_MATRIX_ROWS
:
1262 case D3DXPC_MATRIX_COLUMNS
:
1267 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c
->desc
.Class
));
1268 return D3DERR_INVALIDCALL
;
1272 static HRESULT
set_scalar_array(struct ID3DXConstantTableImpl
*table
, IDirect3DDevice9
*device
, D3DXHANDLE constant
,
1273 const void *indata
, UINT count
, D3DXPARAMETER_TYPE intype
)
1275 struct ctab_constant
*c
= get_valid_constant(table
, constant
);
1279 WARN("Invalid argument specified\n");
1280 return D3DERR_INVALIDCALL
;
1283 switch (c
->desc
.Class
)
1287 case D3DXPC_MATRIX_ROWS
:
1288 case D3DXPC_MATRIX_COLUMNS
:
1290 set(table
, device
, c
, &indata
, intype
, &count
, c
->desc
.Columns
, D3DXPC_SCALAR
, 0, FALSE
);
1294 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c
->desc
.Class
));
1295 return D3DERR_INVALIDCALL
;
1299 static HRESULT
set_vector(struct ID3DXConstantTableImpl
*table
, IDirect3DDevice9
*device
, D3DXHANDLE constant
,
1300 const void *indata
, D3DXPARAMETER_TYPE intype
)
1302 struct ctab_constant
*c
= get_valid_constant(table
, constant
);
1307 WARN("Invalid argument specified\n");
1308 return D3DERR_INVALIDCALL
;
1311 switch (c
->desc
.Class
)
1316 set(table
, device
, c
, &indata
, intype
, &count
, 4, D3DXPC_VECTOR
, 0, FALSE
);
1319 case D3DXPC_MATRIX_ROWS
:
1320 case D3DXPC_MATRIX_COLUMNS
:
1324 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c
->desc
.Class
));
1325 return D3DERR_INVALIDCALL
;
1329 static HRESULT
set_vector_array(struct ID3DXConstantTableImpl
*table
, IDirect3DDevice9
*device
, D3DXHANDLE constant
,
1330 const void *indata
, UINT count
, D3DXPARAMETER_TYPE intype
)
1332 struct ctab_constant
*c
= get_valid_constant(table
, constant
);
1336 WARN("Invalid argument specified\n");
1337 return D3DERR_INVALIDCALL
;
1340 switch (c
->desc
.Class
)
1344 case D3DXPC_MATRIX_ROWS
:
1345 case D3DXPC_MATRIX_COLUMNS
:
1348 set(table
, device
, c
, &indata
, intype
, &count
, 4, D3DXPC_VECTOR
, 0, FALSE
);
1352 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c
->desc
.Class
));
1353 return D3DERR_INVALIDCALL
;
1357 static HRESULT
set_matrix_array(struct ID3DXConstantTableImpl
*table
, IDirect3DDevice9
*device
, D3DXHANDLE constant
,
1358 const void *indata
, UINT count
, BOOL transpose
)
1360 struct ctab_constant
*c
= get_valid_constant(table
, constant
);
1364 WARN("Invalid argument specified\n");
1365 return D3DERR_INVALIDCALL
;
1368 switch (c
->desc
.Class
)
1372 case D3DXPC_MATRIX_ROWS
:
1373 case D3DXPC_MATRIX_COLUMNS
:
1376 set(table
, device
, c
, &indata
, D3DXPT_FLOAT
, &count
, 4,
1377 transpose
? D3DXPC_MATRIX_ROWS
: D3DXPC_MATRIX_COLUMNS
, 0, FALSE
);
1381 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c
->desc
.Class
));
1382 return D3DERR_INVALIDCALL
;
1386 static HRESULT
set_matrix_pointer_array(struct ID3DXConstantTableImpl
*table
, IDirect3DDevice9
*device
,
1387 D3DXHANDLE constant
, const void **indata
, UINT count
, BOOL transpose
)
1389 struct ctab_constant
*c
= get_valid_constant(table
, constant
);
1393 WARN("Invalid argument specified\n");
1394 return D3DERR_INVALIDCALL
;
1397 switch (c
->desc
.Class
)
1401 case D3DXPC_MATRIX_ROWS
:
1402 case D3DXPC_MATRIX_COLUMNS
:
1405 set(table
, device
, c
, indata
, D3DXPT_FLOAT
, &count
, 4,
1406 transpose
? D3DXPC_MATRIX_ROWS
: D3DXPC_MATRIX_COLUMNS
, 0, TRUE
);
1410 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(c
->desc
.Class
));
1411 return D3DERR_INVALIDCALL
;
1415 static HRESULT WINAPI
ID3DXConstantTableImpl_SetDefaults(struct ID3DXConstantTable
*iface
,
1416 struct IDirect3DDevice9
*device
)
1418 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1421 TRACE("iface %p, device %p\n", iface
, device
);
1425 WARN("Invalid argument specified\n");
1426 return D3DERR_INVALIDCALL
;
1429 for (i
= 0; i
< This
->desc
.Constants
; i
++)
1431 D3DXCONSTANT_DESC
*desc
= &This
->constants
[i
].desc
;
1434 if (!desc
->DefaultValue
)
1437 switch (desc
->RegisterSet
)
1440 if (is_vertex_shader(This
->desc
.Version
))
1441 hr
= IDirect3DDevice9_SetVertexShaderConstantB(device
, desc
->RegisterIndex
, desc
->DefaultValue
,
1442 desc
->RegisterCount
);
1444 hr
= IDirect3DDevice9_SetPixelShaderConstantB(device
, desc
->RegisterIndex
, desc
->DefaultValue
,
1445 desc
->RegisterCount
);
1449 if (is_vertex_shader(This
->desc
.Version
))
1450 hr
= IDirect3DDevice9_SetVertexShaderConstantI(device
, desc
->RegisterIndex
, desc
->DefaultValue
,
1451 desc
->RegisterCount
);
1453 hr
= IDirect3DDevice9_SetPixelShaderConstantI(device
, desc
->RegisterIndex
, desc
->DefaultValue
,
1454 desc
->RegisterCount
);
1458 if (is_vertex_shader(This
->desc
.Version
))
1459 hr
= IDirect3DDevice9_SetVertexShaderConstantF(device
, desc
->RegisterIndex
, desc
->DefaultValue
,
1460 desc
->RegisterCount
);
1462 hr
= IDirect3DDevice9_SetPixelShaderConstantF(device
, desc
->RegisterIndex
, desc
->DefaultValue
,
1463 desc
->RegisterCount
);
1467 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc
->RegisterSet
));
1479 static HRESULT WINAPI
ID3DXConstantTableImpl_SetValue(struct ID3DXConstantTable
*iface
,
1480 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const void *data
, unsigned int bytes
)
1482 struct ID3DXConstantTableImpl
*table
= impl_from_ID3DXConstantTable(iface
);
1483 struct ctab_constant
*c
= get_valid_constant(table
, constant
);
1484 D3DXCONSTANT_DESC
*desc
;
1486 TRACE("iface %p, device %p, constant %p, data %p, bytes %u\n", iface
, device
, constant
, data
, bytes
);
1488 if (!device
|| !c
|| !data
)
1490 WARN("Invalid argument specified\n");
1491 return D3DERR_INVALIDCALL
;
1496 switch (desc
->Class
)
1500 case D3DXPC_MATRIX_ROWS
:
1501 case D3DXPC_MATRIX_COLUMNS
:
1504 set(table
, device
, c
, &data
, desc
->Type
, &bytes
, desc
->Columns
, D3DXPC_SCALAR
, 0, FALSE
);
1508 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(desc
->Class
));
1509 return D3DERR_INVALIDCALL
;
1513 static HRESULT WINAPI
ID3DXConstantTableImpl_SetBool(struct ID3DXConstantTable
*iface
,
1514 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, BOOL b
)
1516 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1518 TRACE("iface %p, device %p, constant %p, b %d\n", iface
, device
, constant
, b
);
1520 return set_scalar(This
, device
, constant
, &b
, D3DXPT_BOOL
);
1523 static HRESULT WINAPI
ID3DXConstantTableImpl_SetBoolArray(struct ID3DXConstantTable
*iface
,
1524 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const BOOL
*b
, UINT count
)
1526 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1528 TRACE("iface %p, device %p, constant %p, b %p, count %d\n", iface
, device
, constant
, b
, count
);
1530 return set_scalar_array(This
, device
, constant
, b
, count
, D3DXPT_BOOL
);
1533 static HRESULT WINAPI
ID3DXConstantTableImpl_SetInt(struct ID3DXConstantTable
*iface
,
1534 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, INT n
)
1536 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1538 TRACE("iface %p, device %p, constant %p, n %d\n", iface
, device
, constant
, n
);
1540 return set_scalar(This
, device
, constant
, &n
, D3DXPT_INT
);
1543 static HRESULT WINAPI
ID3DXConstantTableImpl_SetIntArray(struct ID3DXConstantTable
*iface
,
1544 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const INT
*n
, UINT count
)
1546 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1548 TRACE("iface %p, device %p, constant %p, n %p, count %d\n", iface
, device
, constant
, n
, count
);
1550 return set_scalar_array(This
, device
, constant
, n
, count
, D3DXPT_INT
);
1553 static HRESULT WINAPI
ID3DXConstantTableImpl_SetFloat(struct ID3DXConstantTable
*iface
,
1554 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, float f
)
1556 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1558 TRACE("iface %p, device %p, constant %p, f %f\n", iface
, device
, constant
, f
);
1560 return set_scalar(This
, device
, constant
, &f
, D3DXPT_FLOAT
);
1563 static HRESULT WINAPI
ID3DXConstantTableImpl_SetFloatArray(struct ID3DXConstantTable
*iface
,
1564 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const float *f
, UINT count
)
1566 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1568 TRACE("iface %p, device %p, constant %p, f %p, count %d\n", iface
, device
, constant
, f
, count
);
1570 return set_scalar_array(This
, device
, constant
, f
, count
, D3DXPT_FLOAT
);
1573 static HRESULT WINAPI
ID3DXConstantTableImpl_SetVector(struct ID3DXConstantTable
*iface
,
1574 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXVECTOR4
*vector
)
1576 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1578 TRACE("iface %p, device %p, constant %p, vector %p\n", iface
, device
, constant
, vector
);
1580 return set_vector(This
, device
, constant
, vector
, D3DXPT_FLOAT
);
1583 static HRESULT WINAPI
ID3DXConstantTableImpl_SetVectorArray(struct ID3DXConstantTable
*iface
,
1584 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXVECTOR4
*vector
, UINT count
)
1586 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1588 TRACE("iface %p, device %p, constant %p, vector %p, count %u\n", iface
, device
, constant
, vector
, count
);
1590 return set_vector_array(This
, device
, constant
, vector
, count
, D3DXPT_FLOAT
);
1593 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrix(struct ID3DXConstantTable
*iface
,
1594 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
*matrix
)
1596 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1598 TRACE("iface %p, device %p, constant %p, matrix %p\n", iface
, device
, constant
, matrix
);
1600 return set_matrix_array(This
, device
, constant
, matrix
, 1, FALSE
);
1603 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrixArray(struct ID3DXConstantTable
*iface
,
1604 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
*matrix
, UINT count
)
1606 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1608 TRACE("iface %p, device %p, constant %p, matrix %p, count %u\n", iface
, device
, constant
, matrix
, count
);
1610 return set_matrix_array(This
, device
, constant
, matrix
, count
, FALSE
);
1613 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrixPointerArray(struct ID3DXConstantTable
*iface
,
1614 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
**matrix
, UINT count
)
1616 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1618 TRACE("iface %p, device %p, constant %p, matrix %p, count %u)\n", iface
, device
, constant
, matrix
, count
);
1620 return set_matrix_pointer_array(This
, device
, constant
, (const void **)matrix
, count
, FALSE
);
1623 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrixTranspose(struct ID3DXConstantTable
*iface
,
1624 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
*matrix
)
1626 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1628 TRACE("iface %p, device %p, constant %p, matrix %p\n", iface
, device
, constant
, matrix
);
1630 return set_matrix_array(This
, device
, constant
, matrix
, 1, TRUE
);
1633 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrixTransposeArray(struct ID3DXConstantTable
*iface
,
1634 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
*matrix
, UINT count
)
1636 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1638 TRACE("iface %p, device %p, constant %p, matrix %p, count %u\n", iface
, device
, constant
, matrix
, count
);
1640 return set_matrix_array(This
, device
, constant
, matrix
, count
, TRUE
);
1643 static HRESULT WINAPI
ID3DXConstantTableImpl_SetMatrixTransposePointerArray(struct ID3DXConstantTable
*iface
,
1644 struct IDirect3DDevice9
*device
, D3DXHANDLE constant
, const D3DXMATRIX
**matrix
, UINT count
)
1646 struct ID3DXConstantTableImpl
*This
= impl_from_ID3DXConstantTable(iface
);
1648 TRACE("iface %p, device %p, constant %p, matrix %p, count %u)\n", iface
, device
, constant
, matrix
, count
);
1650 return set_matrix_pointer_array(This
, device
, constant
, (const void **)matrix
, count
, TRUE
);
1653 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl
=
1655 /*** IUnknown methods ***/
1656 ID3DXConstantTableImpl_QueryInterface
,
1657 ID3DXConstantTableImpl_AddRef
,
1658 ID3DXConstantTableImpl_Release
,
1659 /*** ID3DXBuffer methods ***/
1660 ID3DXConstantTableImpl_GetBufferPointer
,
1661 ID3DXConstantTableImpl_GetBufferSize
,
1662 /*** ID3DXConstantTable methods ***/
1663 ID3DXConstantTableImpl_GetDesc
,
1664 ID3DXConstantTableImpl_GetConstantDesc
,
1665 ID3DXConstantTableImpl_GetSamplerIndex
,
1666 ID3DXConstantTableImpl_GetConstant
,
1667 ID3DXConstantTableImpl_GetConstantByName
,
1668 ID3DXConstantTableImpl_GetConstantElement
,
1669 ID3DXConstantTableImpl_SetDefaults
,
1670 ID3DXConstantTableImpl_SetValue
,
1671 ID3DXConstantTableImpl_SetBool
,
1672 ID3DXConstantTableImpl_SetBoolArray
,
1673 ID3DXConstantTableImpl_SetInt
,
1674 ID3DXConstantTableImpl_SetIntArray
,
1675 ID3DXConstantTableImpl_SetFloat
,
1676 ID3DXConstantTableImpl_SetFloatArray
,
1677 ID3DXConstantTableImpl_SetVector
,
1678 ID3DXConstantTableImpl_SetVectorArray
,
1679 ID3DXConstantTableImpl_SetMatrix
,
1680 ID3DXConstantTableImpl_SetMatrixArray
,
1681 ID3DXConstantTableImpl_SetMatrixPointerArray
,
1682 ID3DXConstantTableImpl_SetMatrixTranspose
,
1683 ID3DXConstantTableImpl_SetMatrixTransposeArray
,
1684 ID3DXConstantTableImpl_SetMatrixTransposePointerArray
1687 static HRESULT
parse_ctab_constant_type(const char *ctab
, DWORD typeoffset
, struct ctab_constant
*constant
,
1688 BOOL is_element
, WORD index
, WORD max
, DWORD
*offset
, DWORD nameoffset
, UINT regset
)
1690 const D3DXSHADER_TYPEINFO
*type
= (LPD3DXSHADER_TYPEINFO
)(ctab
+ typeoffset
);
1691 const D3DXSHADER_STRUCTMEMBERINFO
*memberinfo
= NULL
;
1692 HRESULT hr
= D3D_OK
;
1696 constant
->desc
.DefaultValue
= offset
? ctab
+ *offset
: NULL
;
1697 constant
->desc
.Class
= type
->Class
;
1698 constant
->desc
.Type
= type
->Type
;
1699 constant
->desc
.Rows
= type
->Rows
;
1700 constant
->desc
.Columns
= type
->Columns
;
1701 constant
->desc
.Elements
= is_element
? 1 : type
->Elements
;
1702 constant
->desc
.StructMembers
= type
->StructMembers
;
1703 constant
->desc
.Name
= ctab
+ nameoffset
;
1704 constant
->desc
.RegisterSet
= regset
;
1705 constant
->desc
.RegisterIndex
= index
;
1707 TRACE("name %s, elements %u, index %u, defaultvalue %p, regset %s\n", constant
->desc
.Name
,
1708 constant
->desc
.Elements
, index
, constant
->desc
.DefaultValue
,
1709 debug_d3dxparameter_registerset(regset
));
1710 TRACE("class %s, type %s, rows %d, columns %d, elements %d, struct_members %d\n",
1711 debug_d3dxparameter_class(type
->Class
), debug_d3dxparameter_type(type
->Type
),
1712 type
->Rows
, type
->Columns
, type
->Elements
, type
->StructMembers
);
1714 if (type
->Elements
> 1 && !is_element
)
1716 count
= type
->Elements
;
1718 else if ((type
->Class
== D3DXPC_STRUCT
) && type
->StructMembers
)
1720 memberinfo
= (D3DXSHADER_STRUCTMEMBERINFO
*)(ctab
+ type
->StructMemberInfo
);
1721 count
= type
->StructMembers
;
1726 constant
->constants
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*constant
->constants
) * count
);
1727 if (!constant
->constants
)
1729 ERR("Out of memory\n");
1734 for (i
= 0; i
< count
; ++i
)
1736 hr
= parse_ctab_constant_type(ctab
, memberinfo
? memberinfo
[i
].TypeInfo
: typeoffset
,
1737 &constant
->constants
[i
], memberinfo
== NULL
, index
+ size
, max
, offset
,
1738 memberinfo
? memberinfo
[i
].Name
: nameoffset
, regset
);
1742 size
+= constant
->constants
[i
].desc
.RegisterCount
;
1747 WORD offsetdiff
= type
->Columns
* type
->Rows
;
1750 size
= type
->Columns
* type
->Rows
;
1755 fail
= type
->Class
!= D3DXPC_SCALAR
&& type
->Class
!= D3DXPC_VECTOR
1756 && type
->Class
!= D3DXPC_MATRIX_ROWS
&& type
->Class
!= D3DXPC_MATRIX_COLUMNS
;
1761 switch (type
->Class
)
1767 offsetdiff
= type
->Rows
* 4;
1770 case D3DXPC_MATRIX_ROWS
:
1771 offsetdiff
= type
->Rows
* 4;
1772 size
= is_element
? type
->Rows
: max(type
->Rows
, type
->Columns
);
1775 case D3DXPC_MATRIX_COLUMNS
:
1776 offsetdiff
= type
->Columns
* 4;
1777 size
= type
->Columns
;
1786 case D3DXRS_SAMPLER
:
1788 fail
= type
->Class
!= D3DXPC_OBJECT
;
1798 FIXME("Unhandled register set %s, type class %s\n", debug_d3dxparameter_registerset(regset
),
1799 debug_d3dxparameter_class(type
->Class
));
1802 /* offset in bytes => offsetdiff * sizeof(DWORD) */
1803 if (offset
) *offset
+= offsetdiff
* 4;
1806 constant
->desc
.RegisterCount
= max(0, min(max
- index
, size
));
1807 constant
->desc
.Bytes
= 4 * constant
->desc
.Elements
* type
->Rows
* type
->Columns
;
1812 if (constant
->constants
)
1814 for (i
= 0; i
< count
; ++i
)
1816 free_constant(&constant
->constants
[i
]);
1818 HeapFree(GetProcessHeap(), 0, constant
->constants
);
1819 constant
->constants
= NULL
;
1825 HRESULT WINAPI
D3DXGetShaderConstantTableEx(const DWORD
*byte_code
, DWORD flags
, ID3DXConstantTable
**constant_table
)
1827 struct ID3DXConstantTableImpl
*object
= NULL
;
1831 const D3DXSHADER_CONSTANTTABLE
*ctab_header
;
1832 const D3DXSHADER_CONSTANTINFO
*constant_info
;
1835 TRACE("byte_code %p, flags %x, constant_table %p\n", byte_code
, flags
, constant_table
);
1837 if (constant_table
) *constant_table
= NULL
;
1839 if (!byte_code
|| !constant_table
)
1841 WARN("Invalid argument specified.\n");
1842 return D3DERR_INVALIDCALL
;
1845 if (!is_valid_bytecode(*byte_code
))
1847 WARN("Invalid byte_code specified.\n");
1851 if (flags
) FIXME("Flags (%#x) are not handled, yet!\n", flags
);
1853 hr
= D3DXFindShaderComment(byte_code
, MAKEFOURCC('C','T','A','B'), &data
, &size
);
1856 WARN("CTAB not found.\n");
1857 return D3DXERR_INVALIDDATA
;
1860 if (size
< sizeof(*ctab_header
))
1862 WARN("Invalid CTAB size.\n");
1863 return D3DXERR_INVALIDDATA
;
1866 ctab_header
= (const D3DXSHADER_CONSTANTTABLE
*)data
;
1867 if (ctab_header
->Size
!= sizeof(*ctab_header
))
1869 WARN("Invalid D3DXSHADER_CONSTANTTABLE size.\n");
1870 return D3DXERR_INVALIDDATA
;
1873 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1875 return E_OUTOFMEMORY
;
1877 object
->ID3DXConstantTable_iface
.lpVtbl
= &ID3DXConstantTable_Vtbl
;
1880 object
->ctab
= HeapAlloc(GetProcessHeap(), 0, size
);
1883 ERR("Out of memory\n");
1884 HeapFree(GetProcessHeap(), 0, object
);
1885 return E_OUTOFMEMORY
;
1887 object
->size
= size
;
1888 memcpy(object
->ctab
, data
, object
->size
);
1890 object
->desc
.Creator
= ctab_header
->Creator
? object
->ctab
+ ctab_header
->Creator
: NULL
;
1891 object
->desc
.Version
= ctab_header
->Version
;
1892 object
->desc
.Constants
= ctab_header
->Constants
;
1893 TRACE("Creator %s, Version %x, Constants %u, Target %s\n",
1894 debugstr_a(object
->desc
.Creator
), object
->desc
.Version
, object
->desc
.Constants
,
1895 debugstr_a(ctab_header
->Target
? object
->ctab
+ ctab_header
->Target
: NULL
));
1897 object
->constants
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1898 sizeof(*object
->constants
) * object
->desc
.Constants
);
1899 if (!object
->constants
)
1901 ERR("Out of memory\n");
1906 constant_info
= (const D3DXSHADER_CONSTANTINFO
*)(object
->ctab
+ ctab_header
->ConstantInfo
);
1907 for (i
= 0; i
< ctab_header
->Constants
; i
++)
1909 DWORD offset
= constant_info
[i
].DefaultValue
;
1911 hr
= parse_ctab_constant_type(object
->ctab
, constant_info
[i
].TypeInfo
,
1912 &object
->constants
[i
], FALSE
, constant_info
[i
].RegisterIndex
,
1913 constant_info
[i
].RegisterIndex
+ constant_info
[i
].RegisterCount
,
1914 offset
? &offset
: NULL
, constant_info
[i
].Name
, constant_info
[i
].RegisterSet
);
1919 * Set the register count, it may differ for D3DXRS_INT4, because somehow
1920 * it makes the assumption that the register size is 1 instead of 4, so the
1921 * count is 4 times bigger. This holds true only for toplevel shader
1922 * constants. The count of elements and members is always based on a
1923 * register size of 4.
1925 if (object
->constants
[i
].desc
.RegisterSet
== D3DXRS_INT4
)
1927 object
->constants
[i
].desc
.RegisterCount
= constant_info
[i
].RegisterCount
;
1931 *constant_table
= &object
->ID3DXConstantTable_iface
;
1936 free_constant_table(object
);
1937 HeapFree(GetProcessHeap(), 0, object
);
1942 HRESULT WINAPI
D3DXGetShaderConstantTable(const DWORD
*byte_code
, ID3DXConstantTable
**constant_table
)
1944 TRACE("(%p, %p): Forwarded to D3DXGetShaderConstantTableEx\n", byte_code
, constant_table
);
1946 return D3DXGetShaderConstantTableEx(byte_code
, 0, constant_table
);
1949 HRESULT WINAPI
D3DXGetShaderSamplers(const DWORD
*byte_code
, const char **samplers
, UINT
*count
)
1951 UINT i
, sampler_count
= 0;
1954 const D3DXSHADER_CONSTANTTABLE
*ctab_header
;
1955 const D3DXSHADER_CONSTANTINFO
*constant_info
;
1957 TRACE("byte_code %p, samplers %p, count %p\n", byte_code
, samplers
, count
);
1959 if (count
) *count
= 0;
1961 if (D3DXFindShaderComment(byte_code
, MAKEFOURCC('C','T','A','B'), (const void **)&data
, &size
) != D3D_OK
)
1964 if (size
< sizeof(*ctab_header
)) return D3D_OK
;
1966 ctab_header
= (const D3DXSHADER_CONSTANTTABLE
*)data
;
1967 if (ctab_header
->Size
!= sizeof(*ctab_header
)) return D3D_OK
;
1969 constant_info
= (const D3DXSHADER_CONSTANTINFO
*)(data
+ ctab_header
->ConstantInfo
);
1970 for (i
= 0; i
< ctab_header
->Constants
; i
++)
1972 const D3DXSHADER_TYPEINFO
*type
;
1974 TRACE("name = %s\n", data
+ constant_info
[i
].Name
);
1976 type
= (const D3DXSHADER_TYPEINFO
*)(data
+ constant_info
[i
].TypeInfo
);
1978 if (type
->Type
== D3DXPT_SAMPLER
1979 || type
->Type
== D3DXPT_SAMPLER1D
1980 || type
->Type
== D3DXPT_SAMPLER2D
1981 || type
->Type
== D3DXPT_SAMPLER3D
1982 || type
->Type
== D3DXPT_SAMPLERCUBE
)
1984 if (samplers
) samplers
[sampler_count
] = data
+ constant_info
[i
].Name
;
1990 TRACE("Found %u samplers\n", sampler_count
);
1992 if (count
) *count
= sampler_count
;