d3dx9: Introduce a function for copying pixels.
[wine.git] / dlls / d3dx9_36 / shader.c
blob3c92992c889adacc00c69133dda2b499561bfd4d
1 /*
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 "config.h"
22 #include "wine/port.h"
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
26 #include "wine/debug.h"
27 #include "wine/unicode.h"
28 #include "windef.h"
29 #include "wingdi.h"
30 #include "objbase.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,
40 UINT flags,
41 ID3DBlob **shader, ID3DBlob **error_messages);
43 const char * WINAPI D3DXGetPixelShaderProfile(struct IDirect3DDevice9 *device)
45 D3DCAPS9 caps;
47 TRACE("device %p\n", device);
49 if (!device) return NULL;
51 IDirect3DDevice9_GetDeviceCaps(device,&caps);
53 switch (caps.PixelShaderVersion)
55 case D3DPS_VERSION(1, 1):
56 return "ps_1_1";
58 case D3DPS_VERSION(1, 2):
59 return "ps_1_2";
61 case D3DPS_VERSION(1, 3):
62 return "ps_1_3";
64 case D3DPS_VERSION(1, 4):
65 return "ps_1_4";
67 case D3DPS_VERSION(2, 0):
68 if ((caps.PS20Caps.NumTemps>=22) &&
69 (caps.PS20Caps.Caps&D3DPS20CAPS_ARBITRARYSWIZZLE) &&
70 (caps.PS20Caps.Caps&D3DPS20CAPS_GRADIENTINSTRUCTIONS) &&
71 (caps.PS20Caps.Caps&D3DPS20CAPS_PREDICATION) &&
72 (caps.PS20Caps.Caps&D3DPS20CAPS_NODEPENDENTREADLIMIT) &&
73 (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
75 return "ps_2_a";
77 if ((caps.PS20Caps.NumTemps>=32) &&
78 (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
80 return "ps_2_b";
82 return "ps_2_0";
84 case D3DPS_VERSION(3, 0):
85 return "ps_3_0";
88 return NULL;
91 UINT WINAPI D3DXGetShaderSize(const DWORD *byte_code)
93 const DWORD *ptr = byte_code;
95 TRACE("byte_code %p\n", byte_code);
97 if (!ptr) return 0;
99 /* Look for the END token, skipping the VERSION token */
100 while (*++ptr != D3DSIO_END)
102 /* Skip comments */
103 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
105 ptr += ((*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT);
108 ++ptr;
110 /* Return the shader size in bytes */
111 return (ptr - byte_code) * sizeof(*ptr);
114 DWORD WINAPI D3DXGetShaderVersion(const DWORD *byte_code)
116 TRACE("byte_code %p\n", byte_code);
118 return byte_code ? *byte_code : 0;
121 const char * WINAPI D3DXGetVertexShaderProfile(struct IDirect3DDevice9 *device)
123 D3DCAPS9 caps;
125 TRACE("device %p\n", device);
127 if (!device) return NULL;
129 IDirect3DDevice9_GetDeviceCaps(device,&caps);
131 switch (caps.VertexShaderVersion)
133 case D3DVS_VERSION(1, 1):
134 return "vs_1_1";
135 case D3DVS_VERSION(2, 0):
136 if ((caps.VS20Caps.NumTemps>=13) &&
137 (caps.VS20Caps.DynamicFlowControlDepth==24) &&
138 (caps.VS20Caps.Caps&D3DPS20CAPS_PREDICATION))
140 return "vs_2_a";
142 return "vs_2_0";
143 case D3DVS_VERSION(3, 0):
144 return "vs_3_0";
147 return NULL;
150 HRESULT WINAPI D3DXFindShaderComment(CONST DWORD* byte_code, DWORD fourcc, LPCVOID* data, UINT* size)
152 CONST DWORD *ptr = byte_code;
154 TRACE("(%p, %x, %p, %p)\n", byte_code, fourcc, data, size);
156 if (data) *data = NULL;
157 if (size) *size = 0;
159 if (!byte_code)
160 return D3DERR_INVALIDCALL;
162 while (*++ptr != D3DSIO_END)
164 /* Check if it is a comment */
165 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
167 DWORD comment_size = (*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
169 /* Check if this is the comment we are looking for */
170 if (*(ptr + 1) == fourcc)
172 UINT ctab_size = (comment_size - 1) * sizeof(DWORD);
173 LPCVOID ctab_data = ptr + 2;
174 if (size)
175 *size = ctab_size;
176 if (data)
177 *data = ctab_data;
178 TRACE("Returning comment data at %p with size %d\n", ctab_data, ctab_size);
179 return D3D_OK;
181 ptr += comment_size;
185 return S_FALSE;
188 HRESULT WINAPI D3DXAssembleShader(LPCSTR data,
189 UINT data_len,
190 CONST D3DXMACRO* defines,
191 LPD3DXINCLUDE include,
192 DWORD flags,
193 LPD3DXBUFFER* shader,
194 LPD3DXBUFFER* error_messages)
196 /* Forward to d3dcompiler: the parameter types aren't really different,
197 the actual data types are equivalent */
198 HRESULT hr = D3DAssemble(data, data_len, NULL, (D3D_SHADER_MACRO *)defines,
199 (ID3DInclude *)include, flags, (ID3DBlob **)shader,
200 (ID3DBlob **)error_messages);
202 if(hr == E_FAIL) hr = D3DXERR_INVALIDDATA;
203 return hr;
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;
218 HANDLE file;
219 UINT size;
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);
229 if(!pathname)
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)
237 goto error;
239 TRACE("Include file found at pathname = %s\n", debugstr_a(pathname));
241 size = GetFileSize(file, NULL);
242 if(size == INVALID_FILE_SIZE)
243 goto error;
245 buffer = HeapAlloc(GetProcessHeap(), 0, size + sizeof(char *));
246 if(!buffer)
247 goto error;
248 *buffer = pathname;
249 if(!ReadFile(file, buffer + 1, size, bytes, NULL))
250 goto error;
252 *data = buffer + 1;
254 CloseHandle(file);
255 return S_OK;
257 error:
258 CloseHandle(file);
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);
267 return S_OK;
270 static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl = {
271 d3dincludefromfile_open,
272 d3dincludefromfile_close
275 struct D3DXIncludeImpl {
276 ID3DXInclude ID3DXInclude_iface;
279 HRESULT WINAPI D3DXAssembleShaderFromFileA(LPCSTR filename,
280 CONST D3DXMACRO* defines,
281 LPD3DXINCLUDE include,
282 DWORD flags,
283 LPD3DXBUFFER* shader,
284 LPD3DXBUFFER* error_messages)
286 LPWSTR filename_w = NULL;
287 DWORD len;
288 HRESULT ret;
290 if (!filename) return D3DXERR_INVALIDDATA;
292 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
293 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
294 if (!filename_w) return E_OUTOFMEMORY;
295 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
297 ret = D3DXAssembleShaderFromFileW(filename_w, defines, include, flags, shader, error_messages);
299 HeapFree(GetProcessHeap(), 0, filename_w);
300 return ret;
303 HRESULT WINAPI D3DXAssembleShaderFromFileW(LPCWSTR filename,
304 CONST D3DXMACRO* defines,
305 LPD3DXINCLUDE include,
306 DWORD flags,
307 LPD3DXBUFFER* shader,
308 LPD3DXBUFFER* error_messages)
310 void *buffer;
311 DWORD len;
312 HRESULT hr;
313 struct D3DXIncludeImpl includefromfile;
315 if(FAILED(map_view_of_file(filename, &buffer, &len)))
316 return D3DXERR_INVALIDDATA;
318 if(!include)
320 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
321 include = &includefromfile.ID3DXInclude_iface;
324 hr = D3DXAssembleShader(buffer, len, defines, include, flags,
325 shader, error_messages);
327 UnmapViewOfFile(buffer);
328 return hr;
331 HRESULT WINAPI D3DXAssembleShaderFromResourceA(HMODULE module,
332 LPCSTR resource,
333 CONST D3DXMACRO* defines,
334 LPD3DXINCLUDE include,
335 DWORD flags,
336 LPD3DXBUFFER* shader,
337 LPD3DXBUFFER* error_messages)
339 HRSRC res;
340 LPCSTR buffer;
341 DWORD len;
343 if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
344 return D3DXERR_INVALIDDATA;
345 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
346 return D3DXERR_INVALIDDATA;
347 return D3DXAssembleShader(buffer, len, defines, include, flags,
348 shader, error_messages);
351 HRESULT WINAPI D3DXAssembleShaderFromResourceW(HMODULE module,
352 LPCWSTR resource,
353 CONST D3DXMACRO* defines,
354 LPD3DXINCLUDE include,
355 DWORD flags,
356 LPD3DXBUFFER* shader,
357 LPD3DXBUFFER* error_messages)
359 HRSRC res;
360 LPCSTR buffer;
361 DWORD len;
363 if (!(res = FindResourceW(module, resource, (LPCWSTR)RT_RCDATA)))
364 return D3DXERR_INVALIDDATA;
365 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
366 return D3DXERR_INVALIDDATA;
367 return D3DXAssembleShader(buffer, len, defines, include, flags,
368 shader, error_messages);
371 HRESULT WINAPI D3DXCompileShader(LPCSTR pSrcData,
372 UINT srcDataLen,
373 CONST D3DXMACRO* pDefines,
374 LPD3DXINCLUDE pInclude,
375 LPCSTR pFunctionName,
376 LPCSTR pProfile,
377 DWORD Flags,
378 LPD3DXBUFFER* ppShader,
379 LPD3DXBUFFER* ppErrorMsgs,
380 LPD3DXCONSTANTTABLE * ppConstantTable)
382 HRESULT hr = D3DCompile(pSrcData, srcDataLen, NULL,
383 (D3D_SHADER_MACRO *)pDefines, (ID3DInclude *)pInclude,
384 pFunctionName, pProfile, Flags, 0,
385 (ID3DBlob **)ppShader, (ID3DBlob **)ppErrorMsgs);
387 if(SUCCEEDED(hr) && ppConstantTable)
388 return D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*ppShader),
389 ppConstantTable);
390 return hr;
393 HRESULT WINAPI D3DXCompileShaderFromFileA(LPCSTR filename,
394 CONST D3DXMACRO* defines,
395 LPD3DXINCLUDE include,
396 LPCSTR entrypoint,
397 LPCSTR profile,
398 DWORD flags,
399 LPD3DXBUFFER* shader,
400 LPD3DXBUFFER* error_messages,
401 LPD3DXCONSTANTTABLE* constant_table)
403 LPWSTR filename_w = NULL;
404 DWORD len;
405 HRESULT ret;
407 if (!filename) return D3DXERR_INVALIDDATA;
409 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
410 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
411 if (!filename_w) return E_OUTOFMEMORY;
412 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
414 ret = D3DXCompileShaderFromFileW(filename_w, defines, include,
415 entrypoint, profile, flags,
416 shader, error_messages, constant_table);
418 HeapFree(GetProcessHeap(), 0, filename_w);
419 return ret;
422 HRESULT WINAPI D3DXCompileShaderFromFileW(LPCWSTR filename,
423 CONST D3DXMACRO* defines,
424 LPD3DXINCLUDE include,
425 LPCSTR entrypoint,
426 LPCSTR profile,
427 DWORD flags,
428 LPD3DXBUFFER* shader,
429 LPD3DXBUFFER* error_messages,
430 LPD3DXCONSTANTTABLE* constant_table)
432 void *buffer;
433 DWORD len, filename_len;
434 HRESULT hr;
435 struct D3DXIncludeImpl includefromfile;
436 char *filename_a;
438 if (FAILED(map_view_of_file(filename, &buffer, &len)))
439 return D3DXERR_INVALIDDATA;
441 if (!include)
443 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
444 include = &includefromfile.ID3DXInclude_iface;
447 filename_len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
448 filename_a = HeapAlloc(GetProcessHeap(), 0, filename_len * sizeof(char));
449 if (!filename_a)
451 UnmapViewOfFile(buffer);
452 return E_OUTOFMEMORY;
454 WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, filename_len, NULL, NULL);
456 hr = D3DCompile(buffer, len, filename_a, (const D3D_SHADER_MACRO *)defines,
457 (ID3DInclude *)include, entrypoint, profile, flags, 0,
458 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
460 if (SUCCEEDED(hr) && constant_table)
461 hr = D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader),
462 constant_table);
464 HeapFree(GetProcessHeap(), 0, filename_a);
465 UnmapViewOfFile(buffer);
466 return hr;
469 HRESULT WINAPI D3DXCompileShaderFromResourceA(HMODULE module,
470 LPCSTR resource,
471 CONST D3DXMACRO* defines,
472 LPD3DXINCLUDE include,
473 LPCSTR entrypoint,
474 LPCSTR profile,
475 DWORD flags,
476 LPD3DXBUFFER* shader,
477 LPD3DXBUFFER* error_messages,
478 LPD3DXCONSTANTTABLE* constant_table)
480 HRSRC res;
481 LPCSTR buffer;
482 DWORD len;
484 if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
485 return D3DXERR_INVALIDDATA;
486 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
487 return D3DXERR_INVALIDDATA;
488 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
489 flags, shader, error_messages, constant_table);
492 HRESULT WINAPI D3DXCompileShaderFromResourceW(HMODULE module,
493 LPCWSTR resource,
494 CONST D3DXMACRO* defines,
495 LPD3DXINCLUDE include,
496 LPCSTR entrypoint,
497 LPCSTR profile,
498 DWORD flags,
499 LPD3DXBUFFER* shader,
500 LPD3DXBUFFER* error_messages,
501 LPD3DXCONSTANTTABLE* constant_table)
503 HRSRC res;
504 LPCSTR buffer;
505 DWORD len;
507 if (!(res = FindResourceW(module, resource, (LPCWSTR)RT_RCDATA)))
508 return D3DXERR_INVALIDDATA;
509 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
510 return D3DXERR_INVALIDDATA;
511 return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
512 flags, shader, error_messages, constant_table);
515 HRESULT WINAPI D3DXPreprocessShader(LPCSTR data,
516 UINT data_len,
517 CONST D3DXMACRO* defines,
518 LPD3DXINCLUDE include,
519 LPD3DXBUFFER* shader,
520 LPD3DXBUFFER* error_messages)
522 TRACE("Forward to D3DPreprocess\n");
523 return D3DPreprocess(data, data_len, NULL,
524 (const D3D_SHADER_MACRO *)defines, (ID3DInclude *)include,
525 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
528 HRESULT WINAPI D3DXPreprocessShaderFromFileA(LPCSTR filename,
529 CONST D3DXMACRO* defines,
530 LPD3DXINCLUDE include,
531 LPD3DXBUFFER* shader,
532 LPD3DXBUFFER* error_messages)
534 WCHAR *filename_w = NULL;
535 DWORD len;
536 HRESULT ret;
538 if (!filename) return D3DXERR_INVALIDDATA;
540 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
541 filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
542 if (!filename_w) return E_OUTOFMEMORY;
543 MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
545 ret = D3DXPreprocessShaderFromFileW(filename_w, defines, include, shader, error_messages);
547 HeapFree(GetProcessHeap(), 0, filename_w);
548 return ret;
551 HRESULT WINAPI D3DXPreprocessShaderFromFileW(LPCWSTR filename,
552 CONST D3DXMACRO* defines,
553 LPD3DXINCLUDE include,
554 LPD3DXBUFFER* shader,
555 LPD3DXBUFFER* error_messages)
557 void *buffer;
558 DWORD len;
559 HRESULT hr;
560 struct D3DXIncludeImpl includefromfile;
562 if (FAILED(map_view_of_file(filename, &buffer, &len)))
563 return D3DXERR_INVALIDDATA;
565 if (!include)
567 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
568 include = &includefromfile.ID3DXInclude_iface;
571 hr = D3DPreprocess(buffer, len, NULL,
572 (const D3D_SHADER_MACRO *)defines,
573 (ID3DInclude *) include,
574 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
576 UnmapViewOfFile(buffer);
577 return hr;
580 HRESULT WINAPI D3DXPreprocessShaderFromResourceA(HMODULE module,
581 LPCSTR resource,
582 CONST D3DXMACRO* defines,
583 LPD3DXINCLUDE include,
584 LPD3DXBUFFER* shader,
585 LPD3DXBUFFER* error_messages)
587 HRSRC res;
588 const char *buffer;
589 DWORD len;
591 if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
592 return D3DXERR_INVALIDDATA;
593 if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
594 return D3DXERR_INVALIDDATA;
595 return D3DXPreprocessShader(buffer, len, defines, include,
596 shader, error_messages);
599 HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module,
600 LPCWSTR resource,
601 CONST D3DXMACRO* defines,
602 LPD3DXINCLUDE include,
603 LPD3DXBUFFER* shader,
604 LPD3DXBUFFER* error_messages)
606 HRSRC res;
607 const char *buffer;
608 DWORD len;
610 if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
611 return D3DXERR_INVALIDDATA;
612 if (FAILED(load_resource_into_memory(module, res, (void **)&buffer, &len)))
613 return D3DXERR_INVALIDDATA;
614 return D3DXPreprocessShader(buffer, len, defines, include,
615 shader, error_messages);
619 struct ctab_constant {
620 D3DXCONSTANT_DESC desc;
621 struct ctab_constant *constants;
624 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl;
626 struct ID3DXConstantTableImpl {
627 ID3DXConstantTable ID3DXConstantTable_iface;
628 LONG ref;
629 char *ctab;
630 DWORD size;
631 D3DXCONSTANTTABLE_DESC desc;
632 struct ctab_constant *constants;
635 static void free_constant(struct ctab_constant *constant)
637 if (constant->constants)
639 UINT i, count = constant->desc.Elements > 1 ? constant->desc.Elements : constant->desc.StructMembers;
641 for (i = 0; i < count; ++i)
643 free_constant(&constant->constants[i]);
645 HeapFree(GetProcessHeap(), 0, constant->constants);
649 static void free_constant_table(struct ID3DXConstantTableImpl *table)
651 if (table->constants)
653 UINT i;
655 for (i = 0; i < table->desc.Constants; ++i)
657 free_constant(&table->constants[i]);
659 HeapFree(GetProcessHeap(), 0, table->constants);
661 HeapFree(GetProcessHeap(), 0, table->ctab);
664 static inline struct ID3DXConstantTableImpl *impl_from_ID3DXConstantTable(ID3DXConstantTable *iface)
666 return CONTAINING_RECORD(iface, struct ID3DXConstantTableImpl, ID3DXConstantTable_iface);
669 static inline int is_vertex_shader(DWORD version)
671 return (version & 0xFFFF0000) == 0xFFFE0000;
674 static inline struct ctab_constant *constant_from_handle(D3DXHANDLE handle)
676 return (struct ctab_constant *)handle;
679 static inline D3DXHANDLE handle_from_constant(struct ctab_constant *constant)
681 return (D3DXHANDLE)constant;
684 static struct ctab_constant *get_constant_by_name(struct ID3DXConstantTableImpl *, struct ctab_constant *, LPCSTR);
686 static struct ctab_constant *get_constant_element_by_name(struct ctab_constant *constant, LPCSTR name)
688 UINT element;
689 LPCSTR part;
691 TRACE("constant %p, name %s\n", constant, debugstr_a(name));
693 if (!name || !*name) return NULL;
695 element = atoi(name);
696 part = strchr(name, ']') + 1;
698 if (constant->desc.Elements > element)
700 struct ctab_constant *c = constant->constants ? &constant->constants[element] : constant;
702 switch (*part++)
704 case '.':
705 return get_constant_by_name(NULL, c, part);
707 case '[':
708 return get_constant_element_by_name(c, part);
710 case '\0':
711 TRACE("Returning parameter %p\n", c);
712 return c;
714 default:
715 FIXME("Unhandled case \"%c\"\n", *--part);
716 break;
720 TRACE("Constant not found\n");
721 return NULL;
724 static struct ctab_constant *get_constant_by_name(struct ID3DXConstantTableImpl *table,
725 struct ctab_constant *constant, LPCSTR name)
727 UINT i, count, length;
728 struct ctab_constant *handles;
729 LPCSTR part;
731 TRACE("table %p, constant %p, name %s\n", table, constant, debugstr_a(name));
733 if (!name || !*name) return NULL;
735 if (!constant)
737 count = table->desc.Constants;
738 handles = table->constants;
740 else
742 count = constant->desc.StructMembers;
743 handles = constant->constants;
746 length = strcspn(name, "[.");
747 part = name + length;
749 for (i = 0; i < count; i++)
751 if (strlen(handles[i].desc.Name) == length && !strncmp(handles[i].desc.Name, name, length))
753 switch (*part++)
755 case '.':
756 return get_constant_by_name(NULL, &handles[i], part);
758 case '[':
759 return get_constant_element_by_name(&handles[i], part);
761 default:
762 TRACE("Returning parameter %p\n", &handles[i]);
763 return &handles[i];
768 TRACE("Constant not found\n");
769 return NULL;
772 static struct ctab_constant *is_valid_sub_constant(struct ctab_constant *parent, struct ctab_constant *constant)
774 UINT i, count;
776 /* all variable have at least elements = 1, but no elements */
777 if (!parent->constants) return NULL;
779 if (parent->desc.Elements > 1) count = parent->desc.Elements;
780 else count = parent->desc.StructMembers;
782 for (i = 0; i < count; ++i)
784 if (&parent->constants[i] == constant)
785 return constant;
787 if (is_valid_sub_constant(&parent->constants[i], constant))
788 return constant;
791 return NULL;
794 static inline struct ctab_constant *is_valid_constant(struct ID3DXConstantTableImpl *table, D3DXHANDLE handle)
796 struct ctab_constant *c = constant_from_handle(handle);
797 UINT i;
799 if (!c) return NULL;
801 for (i = 0; i < table->desc.Constants; ++i)
803 if (&table->constants[i] == c)
804 return c;
806 if (is_valid_sub_constant(&table->constants[i], c))
807 return c;
810 return NULL;
813 static inline struct ctab_constant *get_valid_constant(struct ID3DXConstantTableImpl *table, D3DXHANDLE handle)
815 struct ctab_constant *constant = is_valid_constant(table, handle);
817 if (!constant) constant = get_constant_by_name(table, NULL, handle);
819 return constant;
822 static inline void set_float_shader_constant(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device,
823 UINT register_index, const FLOAT *data, UINT count)
825 if (is_vertex_shader(table->desc.Version))
826 IDirect3DDevice9_SetVertexShaderConstantF(device, register_index, data, count);
827 else
828 IDirect3DDevice9_SetPixelShaderConstantF(device, register_index, data, count);
831 /*** IUnknown methods ***/
832 static HRESULT WINAPI ID3DXConstantTableImpl_QueryInterface(ID3DXConstantTable *iface, REFIID riid, void **out)
834 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
836 if (IsEqualGUID(riid, &IID_IUnknown) ||
837 IsEqualGUID(riid, &IID_ID3DXBuffer) ||
838 IsEqualGUID(riid, &IID_ID3DXConstantTable))
840 ID3DXConstantTable_AddRef(iface);
841 *out = iface;
842 return S_OK;
845 WARN("Interface %s not found.\n", debugstr_guid(riid));
847 return E_NOINTERFACE;
850 static ULONG WINAPI ID3DXConstantTableImpl_AddRef(ID3DXConstantTable *iface)
852 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
854 TRACE("(%p)->(): AddRef from %d\n", This, This->ref);
856 return InterlockedIncrement(&This->ref);
859 static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable *iface)
861 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
862 ULONG ref = InterlockedDecrement(&This->ref);
864 TRACE("(%p)->(): Release from %d\n", This, ref + 1);
866 if (!ref)
868 free_constant_table(This);
869 HeapFree(GetProcessHeap(), 0, This);
872 return ref;
875 /*** ID3DXBuffer methods ***/
876 static LPVOID WINAPI ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable *iface)
878 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
880 TRACE("(%p)->()\n", This);
882 return This->ctab;
885 static DWORD WINAPI ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable *iface)
887 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
889 TRACE("(%p)->()\n", This);
891 return This->size;
894 /*** ID3DXConstantTable methods ***/
895 static HRESULT WINAPI ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable *iface, D3DXCONSTANTTABLE_DESC *desc)
897 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
899 TRACE("(%p)->(%p)\n", This, desc);
901 if (!desc)
902 return D3DERR_INVALIDCALL;
904 *desc = This->desc;
906 return D3D_OK;
909 static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable *iface, D3DXHANDLE constant,
910 D3DXCONSTANT_DESC *desc, UINT *count)
912 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
913 struct ctab_constant *c = get_valid_constant(This, constant);
915 TRACE("(%p)->(%p, %p, %p)\n", This, constant, desc, count);
917 if (!c)
919 WARN("Invalid argument specified\n");
920 return D3DERR_INVALIDCALL;
923 if (desc) *desc = c->desc;
924 if (count) *count = 1;
926 return D3D_OK;
929 static UINT WINAPI ID3DXConstantTableImpl_GetSamplerIndex(ID3DXConstantTable *iface, D3DXHANDLE constant)
931 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
932 struct ctab_constant *c = get_valid_constant(This, constant);
934 TRACE("(%p)->(%p)\n", This, constant);
936 if (!c || c->desc.RegisterSet != D3DXRS_SAMPLER)
938 WARN("Invalid argument specified\n");
939 return (UINT)-1;
942 TRACE("Returning RegisterIndex %u\n", c->desc.RegisterIndex);
943 return c->desc.RegisterIndex;
946 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable *iface, D3DXHANDLE constant, UINT index)
948 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
949 struct ctab_constant *c;
951 TRACE("(%p)->(%p, %d)\n", This, constant, index);
953 if (constant)
955 c = get_valid_constant(This, constant);
956 if (c && index < c->desc.StructMembers)
958 c = &c->constants[index];
959 TRACE("Returning constant %p\n", c);
960 return handle_from_constant(c);
963 else
965 if (index < This->desc.Constants)
967 c = &This->constants[index];
968 TRACE("Returning constant %p\n", c);
969 return handle_from_constant(c);
973 WARN("Index out of range\n");
974 return NULL;
977 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable *iface, D3DXHANDLE constant, LPCSTR name)
979 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
980 struct ctab_constant *c = get_valid_constant(This, constant);
982 TRACE("(%p)->(%p, %s)\n", This, constant, name);
984 c = get_constant_by_name(This, c, name);
985 TRACE("Returning constant %p\n", c);
987 return handle_from_constant(c);
990 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable *iface, D3DXHANDLE constant, UINT index)
992 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
993 struct ctab_constant *c = get_valid_constant(This, constant);
995 TRACE("(%p)->(%p, %d)\n", This, constant, index);
997 if (c && index < c->desc.Elements)
999 if (c->desc.Elements > 1) c = &c->constants[index];
1000 TRACE("Returning constant %p\n", c);
1001 return handle_from_constant(c);
1004 WARN("Invalid argument specified\n");
1005 return NULL;
1008 static HRESULT set_scalar_array(ID3DXConstantTable *iface, IDirect3DDevice9 *device, D3DXHANDLE constant, const void *data,
1009 UINT count, D3DXPARAMETER_TYPE type)
1011 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1012 D3DXCONSTANT_DESC desc;
1013 HRESULT hr;
1014 UINT i, desc_count = 1;
1015 float row[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1017 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
1018 if (FAILED(hr))
1020 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
1021 return D3DERR_INVALIDCALL;
1024 if (desc.Class != D3DXPC_SCALAR)
1025 return D3D_OK;
1027 switch (desc.RegisterSet)
1029 case D3DXRS_FLOAT4:
1030 for (i = 0; i < min(count, desc.RegisterCount); i++)
1032 /* We need the for loop since each IDirect3DDevice9_Set*ShaderConstantF expects a float4 */
1033 switch(type)
1035 case D3DXPT_FLOAT:
1036 row[0] = ((float *)data)[i];
1037 break;
1038 case D3DXPT_INT:
1039 row[0] = (float)((int *)data)[i];
1040 break;
1041 case D3DXPT_BOOL:
1042 row[0] = ((BOOL *)data)[i] ? 1.0f : 0.0f;
1043 break;
1044 default:
1045 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(type));
1046 return D3DERR_INVALIDCALL;
1048 set_float_shader_constant(This, device, desc.RegisterIndex + i, row, 1);
1050 break;
1051 default:
1052 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc.RegisterSet));
1053 return E_NOTIMPL;
1056 return D3D_OK;
1059 static HRESULT set_vector_array(ID3DXConstantTable *iface, IDirect3DDevice9 *device, D3DXHANDLE constant, const void *data,
1060 UINT count, D3DXPARAMETER_TYPE type)
1062 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1063 D3DXCONSTANT_DESC desc;
1064 HRESULT hr;
1065 UINT i, j, desc_count = 1;
1066 float vec[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1068 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
1069 if (FAILED(hr))
1071 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
1072 return D3DERR_INVALIDCALL;
1075 if (desc.Class == D3DXPC_MATRIX_ROWS || desc.Class == D3DXPC_MATRIX_COLUMNS)
1076 return D3D_OK;
1078 switch (desc.RegisterSet)
1080 case D3DXRS_FLOAT4:
1081 for (i = 0; i < min(count, desc.RegisterCount); i++)
1083 switch (type)
1085 case D3DXPT_FLOAT:
1086 memcpy(vec, ((float *)data) + i * desc.Columns, desc.Columns * sizeof(float));
1087 break;
1088 case D3DXPT_INT:
1089 for (j = 0; j < desc.Columns; j++)
1090 vec[j] = (float)((int *)data)[i * desc.Columns + j];
1091 break;
1092 case D3DXPT_BOOL:
1093 for (j = 0; j < desc.Columns; j++)
1094 vec[j] = ((BOOL *)data)[i * desc.Columns + j] ? 1.0f : 0.0f;
1095 break;
1096 default:
1097 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(type));
1098 return D3DERR_INVALIDCALL;
1101 set_float_shader_constant(This, device, desc.RegisterIndex + i, vec, 1);
1103 break;
1104 default:
1105 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc.RegisterSet));
1106 return E_NOTIMPL;
1109 return D3D_OK;
1112 static HRESULT set_float_matrix(FLOAT *matrix, const D3DXCONSTANT_DESC *desc,
1113 UINT row_offset, UINT column_offset, UINT rows, UINT columns,
1114 const void *data, D3DXPARAMETER_TYPE type, UINT src_columns)
1116 UINT i, j;
1118 switch (type)
1120 case D3DXPT_FLOAT:
1121 for (i = 0; i < rows; i++)
1123 for (j = 0; j < columns; j++)
1124 matrix[i * row_offset + j * column_offset] = ((FLOAT *)data)[i * src_columns + j];
1126 break;
1127 case D3DXPT_INT:
1128 for (i = 0; i < rows; i++)
1130 for (j = 0; j < columns; j++)
1131 matrix[i * row_offset + j * column_offset] = ((INT *)data)[i * src_columns + j];
1133 break;
1134 default:
1135 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(type));
1136 return D3DERR_INVALIDCALL;
1139 return D3D_OK;
1142 static HRESULT set_matrix_array(ID3DXConstantTable *iface, IDirect3DDevice9 *device, D3DXHANDLE constant, const void *data,
1143 UINT count, D3DXPARAMETER_CLASS class, D3DXPARAMETER_TYPE type, UINT rows, UINT columns)
1145 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1146 struct ctab_constant *c = get_valid_constant(This, constant);
1147 D3DXCONSTANT_DESC *desc;
1148 UINT registers_per_matrix, num_rows, num_columns, i;
1149 UINT row_offset = 1, column_offset = 1;
1150 const DWORD *data_ptr;
1151 FLOAT matrix[16] = {0.0f, 0.0f, 0.0f, 0.0f,
1152 0.0f, 0.0f, 0.0f, 0.0f,
1153 0.0f, 0.0f, 0.0f, 0.0f,
1154 0.0f, 0.0f, 0.0f, 0.0f};
1156 if (!c)
1158 WARN("Invalid argument specified\n");
1159 return D3DERR_INVALIDCALL;
1161 desc = &c->desc;
1163 if (desc->Class == D3DXPC_MATRIX_ROWS
1164 || desc->Class == D3DXPC_MATRIX_COLUMNS
1165 || desc->Class == D3DXPC_VECTOR
1166 || desc->Class == D3DXPC_SCALAR)
1168 if (desc->Class == class) row_offset = 4;
1169 else column_offset = 4;
1171 if (class == D3DXPC_MATRIX_ROWS)
1173 if (desc->Class == D3DXPC_VECTOR) return D3D_OK;
1175 num_rows = desc->Rows;
1176 num_columns = desc->Columns;
1178 else
1180 num_rows = desc->Columns;
1181 num_columns = desc->Rows;
1184 registers_per_matrix = (desc->Class == D3DXPC_MATRIX_COLUMNS) ? desc->Columns : desc->Rows;
1186 else
1188 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc->Class));
1189 return E_NOTIMPL;
1192 switch (desc->RegisterSet)
1194 case D3DXRS_FLOAT4:
1195 data_ptr = data;
1196 for (i = 0; i < count; i++)
1198 HRESULT hr;
1200 if (registers_per_matrix * (i + 1) > desc->RegisterCount)
1201 break;
1203 hr = set_float_matrix(matrix, desc, row_offset, column_offset, num_rows, num_columns, data_ptr, type, columns);
1204 if (FAILED(hr)) return hr;
1206 set_float_shader_constant(This, device, desc->RegisterIndex + i * registers_per_matrix, matrix, registers_per_matrix);
1208 data_ptr += rows * columns;
1210 break;
1211 default:
1212 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc->RegisterSet));
1213 return E_NOTIMPL;
1216 return D3D_OK;
1219 static HRESULT set_matrix_pointer_array(ID3DXConstantTable *iface, IDirect3DDevice9 *device, D3DXHANDLE constant,
1220 const D3DXMATRIX **data, UINT count, D3DXPARAMETER_CLASS class)
1222 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1223 D3DXCONSTANT_DESC desc;
1224 HRESULT hr;
1225 UINT registers_per_matrix;
1226 UINT i, desc_count = 1;
1227 UINT num_rows, num_columns;
1228 UINT row_offset, column_offset;
1229 FLOAT matrix[16] = {0.0f, 0.0f, 0.0f, 0.0f,
1230 0.0f, 0.0f, 0.0f, 0.0f,
1231 0.0f, 0.0f, 0.0f, 0.0f,
1232 0.0f, 0.0f, 0.0f, 0.0f};
1234 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
1235 if (FAILED(hr))
1237 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
1238 return D3DERR_INVALIDCALL;
1241 if (desc.Class == D3DXPC_MATRIX_ROWS || desc.Class == D3DXPC_MATRIX_COLUMNS)
1243 if (desc.Class == class)
1245 column_offset = 1;
1246 row_offset = 4;
1248 else
1250 column_offset = 4;
1251 row_offset = 1;
1254 if (class == D3DXPC_MATRIX_ROWS)
1256 num_rows = desc.Rows;
1257 num_columns = desc.Columns;
1259 else
1261 num_rows = desc.Columns;
1262 num_columns = desc.Rows;
1265 registers_per_matrix = (desc.Class == D3DXPC_MATRIX_ROWS) ? desc.Rows : desc.Columns;
1267 else if (desc.Class == D3DXPC_SCALAR)
1269 registers_per_matrix = 1;
1270 column_offset = 1;
1271 row_offset = 1;
1272 num_rows = desc.Rows;
1273 num_columns = desc.Columns;
1275 else if (desc.Class == D3DXPC_VECTOR)
1277 registers_per_matrix = 1;
1279 if (class == D3DXPC_MATRIX_ROWS)
1281 column_offset = 1;
1282 row_offset = 4;
1283 num_rows = desc.Rows;
1284 num_columns = desc.Columns;
1286 else
1288 column_offset = 4;
1289 row_offset = 1;
1290 num_rows = desc.Columns;
1291 num_columns = desc.Rows;
1294 else
1296 FIXME("Unhandled variable class %s\n", debug_d3dxparameter_class(desc.Class));
1297 return D3D_OK;
1300 switch (desc.RegisterSet)
1302 case D3DXRS_FLOAT4:
1303 for (i = 0; i < count; i++)
1305 if (registers_per_matrix * (i + 1) > desc.RegisterCount)
1306 break;
1308 hr = set_float_matrix(matrix, &desc, row_offset, column_offset, num_rows, num_columns, *data, D3DXPT_FLOAT, 4);
1309 if (FAILED(hr)) return hr;
1311 set_float_shader_constant(This, device, desc.RegisterIndex + i * registers_per_matrix, matrix, registers_per_matrix);
1313 data++;
1315 break;
1316 default:
1317 FIXME("Unhandled register set %s\n", debug_d3dxparameter_registerset(desc.RegisterSet));
1318 return E_NOTIMPL;
1321 return D3D_OK;
1324 static HRESULT WINAPI ID3DXConstantTableImpl_SetDefaults(struct ID3DXConstantTable *iface,
1325 struct IDirect3DDevice9 *device)
1327 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1328 UINT i;
1330 TRACE("(%p)->(%p)\n", This, device);
1332 if (!device)
1333 return D3DERR_INVALIDCALL;
1335 for (i = 0; i < This->desc.Constants; i++)
1337 D3DXCONSTANT_DESC *desc = &This->constants[i].desc;
1339 if (!desc->DefaultValue)
1340 continue;
1342 set_float_shader_constant(This, device, desc->RegisterIndex, desc->DefaultValue, desc->RegisterCount);
1345 return D3D_OK;
1348 static HRESULT WINAPI ID3DXConstantTableImpl_SetValue(struct ID3DXConstantTable *iface,
1349 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const void *data, UINT bytes)
1351 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1352 HRESULT hr;
1353 UINT elements;
1354 UINT count = 1;
1355 D3DXCONSTANT_DESC desc;
1357 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, data, bytes);
1359 if (!device || !constant || !data)
1360 return D3DERR_INVALIDCALL;
1362 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &count);
1363 if (FAILED(hr))
1364 return hr;
1366 elements = bytes / (desc.Bytes / desc.Elements);
1368 switch (desc.Class)
1370 case D3DXPC_SCALAR:
1371 return set_scalar_array(iface, device, constant, data, elements, desc.Type);
1372 case D3DXPC_VECTOR:
1373 return set_vector_array(iface, device, constant, data, elements, desc.Type);
1374 case D3DXPC_MATRIX_ROWS:
1375 case D3DXPC_MATRIX_COLUMNS:
1376 return set_matrix_array(iface, device, constant, data, elements,
1377 D3DXPC_MATRIX_ROWS, desc.Type, desc.Rows, desc.Columns);
1378 default:
1379 FIXME("Unhandled parameter class %s\n", debug_d3dxparameter_class(desc.Class));
1380 return D3DERR_INVALIDCALL;
1384 static HRESULT WINAPI ID3DXConstantTableImpl_SetBool(struct ID3DXConstantTable *iface,
1385 struct IDirect3DDevice9 *device, D3DXHANDLE constant, BOOL b)
1387 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1389 TRACE("(%p)->(%p, %p, %d)\n", This, device, constant, b);
1391 return set_scalar_array(iface, device, constant, &b, 1, D3DXPT_BOOL);
1394 static HRESULT WINAPI ID3DXConstantTableImpl_SetBoolArray(struct ID3DXConstantTable *iface,
1395 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const BOOL *b, UINT count)
1397 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1399 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, b, count);
1401 return set_scalar_array(iface, device, constant, b, count, D3DXPT_BOOL);
1404 static HRESULT WINAPI ID3DXConstantTableImpl_SetInt(struct ID3DXConstantTable *iface,
1405 struct IDirect3DDevice9 *device, D3DXHANDLE constant, INT n)
1407 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1409 TRACE("(%p)->(%p, %p, %d)\n", This, device, constant, n);
1411 return set_scalar_array(iface, device, constant, &n, 1, D3DXPT_INT);
1414 static HRESULT WINAPI ID3DXConstantTableImpl_SetIntArray(struct ID3DXConstantTable *iface,
1415 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const INT *n, UINT count)
1417 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1419 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, n, count);
1421 return set_scalar_array(iface, device, constant, n, count, D3DXPT_INT);
1424 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloat(struct ID3DXConstantTable *iface,
1425 struct IDirect3DDevice9 *device, D3DXHANDLE constant, float f)
1427 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1429 TRACE("(%p)->(%p, %p, %f)\n", This, device, constant, f);
1431 return set_scalar_array(iface, device, constant, &f, 1, D3DXPT_FLOAT);
1434 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloatArray(struct ID3DXConstantTable *iface,
1435 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const float *f, UINT count)
1437 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1439 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, f, count);
1441 return set_scalar_array(iface, device, constant, f, count, D3DXPT_FLOAT);
1444 static HRESULT WINAPI ID3DXConstantTableImpl_SetVector(struct ID3DXConstantTable *iface,
1445 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXVECTOR4 *vector)
1447 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1449 TRACE("(%p)->(%p, %p, %p)\n", This, device, constant, vector);
1451 return set_vector_array(iface, device, constant, vector, 1, D3DXPT_FLOAT);
1454 static HRESULT WINAPI ID3DXConstantTableImpl_SetVectorArray(struct ID3DXConstantTable *iface,
1455 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXVECTOR4 *vector, UINT count)
1457 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1459 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, vector, count);
1461 return set_vector_array(iface, device, constant, vector, count, D3DXPT_FLOAT);
1464 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrix(struct ID3DXConstantTable *iface,
1465 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix)
1467 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1469 TRACE("(%p)->(%p, %p, %p)\n", This, device, constant, matrix);
1471 return set_matrix_array(iface, device, constant, matrix, 1, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 4, 4);
1474 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixArray(struct ID3DXConstantTable *iface,
1475 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
1477 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1479 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, matrix, count);
1481 return set_matrix_array(iface, device, constant, matrix, count, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 4, 4);
1484 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixPointerArray(struct ID3DXConstantTable *iface,
1485 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
1487 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1489 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, matrix, count);
1491 return set_matrix_pointer_array(iface, device, constant, matrix, count, D3DXPC_MATRIX_ROWS);
1494 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTranspose(struct ID3DXConstantTable *iface,
1495 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix)
1497 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1499 TRACE("(%p)->(%p, %p, %p)\n", This, device, constant, matrix);
1501 return set_matrix_array(iface, device, constant, matrix, 1, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 4, 4);
1504 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposeArray(struct ID3DXConstantTable *iface,
1505 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX *matrix, UINT count)
1507 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1509 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, matrix, count);
1511 return set_matrix_array(iface, device, constant, matrix, count, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 4, 4);
1514 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposePointerArray(struct ID3DXConstantTable *iface,
1515 struct IDirect3DDevice9 *device, D3DXHANDLE constant, const D3DXMATRIX **matrix, UINT count)
1517 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1519 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, matrix, count);
1521 return set_matrix_pointer_array(iface, device, constant, matrix, count, D3DXPC_MATRIX_COLUMNS);
1524 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl =
1526 /*** IUnknown methods ***/
1527 ID3DXConstantTableImpl_QueryInterface,
1528 ID3DXConstantTableImpl_AddRef,
1529 ID3DXConstantTableImpl_Release,
1530 /*** ID3DXBuffer methods ***/
1531 ID3DXConstantTableImpl_GetBufferPointer,
1532 ID3DXConstantTableImpl_GetBufferSize,
1533 /*** ID3DXConstantTable methods ***/
1534 ID3DXConstantTableImpl_GetDesc,
1535 ID3DXConstantTableImpl_GetConstantDesc,
1536 ID3DXConstantTableImpl_GetSamplerIndex,
1537 ID3DXConstantTableImpl_GetConstant,
1538 ID3DXConstantTableImpl_GetConstantByName,
1539 ID3DXConstantTableImpl_GetConstantElement,
1540 ID3DXConstantTableImpl_SetDefaults,
1541 ID3DXConstantTableImpl_SetValue,
1542 ID3DXConstantTableImpl_SetBool,
1543 ID3DXConstantTableImpl_SetBoolArray,
1544 ID3DXConstantTableImpl_SetInt,
1545 ID3DXConstantTableImpl_SetIntArray,
1546 ID3DXConstantTableImpl_SetFloat,
1547 ID3DXConstantTableImpl_SetFloatArray,
1548 ID3DXConstantTableImpl_SetVector,
1549 ID3DXConstantTableImpl_SetVectorArray,
1550 ID3DXConstantTableImpl_SetMatrix,
1551 ID3DXConstantTableImpl_SetMatrixArray,
1552 ID3DXConstantTableImpl_SetMatrixPointerArray,
1553 ID3DXConstantTableImpl_SetMatrixTranspose,
1554 ID3DXConstantTableImpl_SetMatrixTransposeArray,
1555 ID3DXConstantTableImpl_SetMatrixTransposePointerArray
1558 static HRESULT parse_ctab_constant_type(const char *ctab, DWORD typeoffset, struct ctab_constant *constant,
1559 BOOL is_element, WORD index, WORD max, DWORD *offset, DWORD nameoffset, UINT regset)
1561 const D3DXSHADER_TYPEINFO *type = (LPD3DXSHADER_TYPEINFO)(ctab + typeoffset);
1562 const D3DXSHADER_STRUCTMEMBERINFO *memberinfo = NULL;
1563 HRESULT hr = D3D_OK;
1564 UINT i, count = 0;
1565 WORD size = 0;
1567 constant->desc.DefaultValue = offset ? ctab + *offset : NULL;
1568 constant->desc.Class = type->Class;
1569 constant->desc.Type = type->Type;
1570 constant->desc.Rows = type->Rows;
1571 constant->desc.Columns = type->Columns;
1572 constant->desc.Elements = is_element ? 1 : type->Elements;
1573 constant->desc.StructMembers = type->StructMembers;
1574 constant->desc.Name = ctab + nameoffset;
1575 constant->desc.RegisterSet = regset;
1576 constant->desc.RegisterIndex = index;
1578 TRACE("name %s, elements %u, index %u, defaultvalue %p, regset %s\n", constant->desc.Name,
1579 constant->desc.Elements, index, constant->desc.DefaultValue,
1580 debug_d3dxparameter_registerset(regset));
1581 TRACE("class %s, type %s, rows %d, columns %d, elements %d, struct_members %d\n",
1582 debug_d3dxparameter_class(type->Class), debug_d3dxparameter_type(type->Type),
1583 type->Rows, type->Columns, type->Elements, type->StructMembers);
1585 if (type->Elements > 1 && !is_element)
1587 count = type->Elements;
1589 else if ((type->Class == D3DXPC_STRUCT) && type->StructMembers)
1591 memberinfo = (D3DXSHADER_STRUCTMEMBERINFO*)(ctab + type->StructMemberInfo);
1592 count = type->StructMembers;
1595 if (count)
1597 constant->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*constant->constants) * count);
1598 if (!constant->constants)
1600 ERR("Out of memory\n");
1601 hr = E_OUTOFMEMORY;
1602 goto error;
1605 for (i = 0; i < count; ++i)
1607 hr = parse_ctab_constant_type(ctab, memberinfo ? memberinfo[i].TypeInfo : typeoffset,
1608 &constant->constants[i], memberinfo == NULL, index + size, max, offset,
1609 memberinfo ? memberinfo[i].Name : nameoffset, regset);
1610 if (hr != D3D_OK)
1611 goto error;
1613 size += constant->constants[i].desc.RegisterCount;
1616 else
1618 WORD offsetdiff = 0;
1620 switch (type->Class)
1622 case D3DXPC_SCALAR:
1623 case D3DXPC_VECTOR:
1624 offsetdiff = 1;
1625 size = 1;
1626 break;
1628 case D3DXPC_MATRIX_ROWS:
1629 size = is_element ? type->Rows : max(type->Rows, type->Columns);
1630 offsetdiff = type->Rows;
1631 break;
1633 case D3DXPC_MATRIX_COLUMNS:
1634 size = type->Columns;
1635 offsetdiff = type->Columns;
1636 break;
1638 case D3DXPC_OBJECT:
1639 size = 1;
1640 break;
1642 default:
1643 FIXME("Unhandled type class %s\n", debug_d3dxparameter_class(type->Class));
1644 break;
1647 /* offset in bytes => offsetdiff * components(4) * sizeof(DWORD) */
1648 if (offset) *offset += offsetdiff * 4 * 4;
1650 /* int and bool registerset have different sizes */
1651 if (regset == D3DXRS_INT4 || regset == D3DXRS_BOOL)
1653 switch (type->Class)
1655 case D3DXPC_SCALAR:
1656 case D3DXPC_VECTOR:
1657 size = type->Columns;
1658 break;
1660 case D3DXPC_MATRIX_ROWS:
1661 case D3DXPC_MATRIX_COLUMNS:
1662 size = 4 * type->Columns;
1663 break;
1665 default:
1666 FIXME("Unhandled type class %s\n", debug_d3dxparameter_class(type->Class));
1667 break;
1672 constant->desc.RegisterCount = max(0, min(max - index, size));
1673 constant->desc.Bytes = 4 * constant->desc.Elements * type->Rows * type->Columns;
1675 return D3D_OK;
1677 error:
1678 if (constant->constants)
1680 for (i = 0; i < count; ++i)
1682 free_constant(&constant->constants[i]);
1684 HeapFree(GetProcessHeap(), 0, constant->constants);
1685 constant->constants = NULL;
1688 return hr;
1691 HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD *byte_code,
1692 DWORD flags,
1693 LPD3DXCONSTANTTABLE *constant_table)
1695 struct ID3DXConstantTableImpl *object = NULL;
1696 HRESULT hr;
1697 LPCVOID data;
1698 UINT size;
1699 const D3DXSHADER_CONSTANTTABLE* ctab_header;
1700 D3DXSHADER_CONSTANTINFO* constant_info;
1701 DWORD i;
1703 TRACE("(%p, %x, %p)\n", byte_code, flags, constant_table);
1705 if (!byte_code || !constant_table)
1707 WARN("Invalid argument specified.\n");
1708 return D3DERR_INVALIDCALL;
1711 if (flags) FIXME("Flags (%#x) are not handled, yet!\n", flags);
1713 hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), &data, &size);
1714 if (hr != D3D_OK)
1716 WARN("CTAB not found.\n");
1717 return D3DXERR_INVALIDDATA;
1720 if (size < sizeof(D3DXSHADER_CONSTANTTABLE))
1722 WARN("Invalid CTAB size.\n");
1723 return D3DXERR_INVALIDDATA;
1726 ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data;
1727 if (ctab_header->Size != sizeof(D3DXSHADER_CONSTANTTABLE))
1729 WARN("Invalid D3DXSHADER_CONSTANTTABLE size.\n");
1730 return D3DXERR_INVALIDDATA;
1733 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1734 if (!object)
1736 ERR("Out of memory\n");
1737 return E_OUTOFMEMORY;
1740 object->ID3DXConstantTable_iface.lpVtbl = &ID3DXConstantTable_Vtbl;
1741 object->ref = 1;
1743 object->ctab = HeapAlloc(GetProcessHeap(), 0, size);
1744 if (!object->ctab)
1746 ERR("Out of memory\n");
1747 HeapFree(GetProcessHeap(), 0, object);
1748 return E_OUTOFMEMORY;
1750 object->size = size;
1751 memcpy(object->ctab, data, object->size);
1753 object->desc.Creator = ctab_header->Creator ? object->ctab + ctab_header->Creator : NULL;
1754 object->desc.Version = ctab_header->Version;
1755 object->desc.Constants = ctab_header->Constants;
1756 TRACE("Creator %s, Version %x, Constants %u, Target %s\n",
1757 debugstr_a(object->desc.Creator), object->desc.Version, object->desc.Constants,
1758 debugstr_a(ctab_header->Target ? object->ctab + ctab_header->Target : NULL));
1760 object->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1761 sizeof(*object->constants) * object->desc.Constants);
1762 if (!object->constants)
1764 ERR("Out of memory\n");
1765 hr = E_OUTOFMEMORY;
1766 goto error;
1769 constant_info = (LPD3DXSHADER_CONSTANTINFO)(object->ctab + ctab_header->ConstantInfo);
1770 for (i = 0; i < ctab_header->Constants; i++)
1772 DWORD offset = constant_info[i].DefaultValue;
1774 hr = parse_ctab_constant_type(object->ctab, constant_info[i].TypeInfo,
1775 &object->constants[i], FALSE, constant_info[i].RegisterIndex,
1776 constant_info[i].RegisterIndex + constant_info[i].RegisterCount,
1777 offset ? &offset : NULL, constant_info[i].Name, constant_info[i].RegisterSet);
1778 if (hr != D3D_OK)
1779 goto error;
1782 *constant_table = &object->ID3DXConstantTable_iface;
1784 return D3D_OK;
1786 error:
1787 free_constant_table(object);
1788 HeapFree(GetProcessHeap(), 0, object);
1790 return hr;
1793 HRESULT WINAPI D3DXGetShaderConstantTable(CONST DWORD* byte_code,
1794 LPD3DXCONSTANTTABLE* constant_table)
1796 TRACE("(%p, %p): Forwarded to D3DXGetShaderConstantTableEx\n", byte_code, constant_table);
1798 return D3DXGetShaderConstantTableEx(byte_code, 0, constant_table);
1801 HRESULT WINAPI D3DXGetShaderSamplers(CONST DWORD *byte_code, LPCSTR *samplers, UINT *count)
1803 HRESULT hr;
1804 UINT i, sampler_count = 0;
1805 UINT size;
1806 LPCSTR data;
1807 const D3DXSHADER_CONSTANTTABLE *ctab_header;
1808 const D3DXSHADER_CONSTANTINFO *constant_info;
1810 TRACE("byte_code %p, samplers %p, count %p\n", byte_code, samplers, count);
1812 if (count) *count = 0;
1814 hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), (LPCVOID *)&data, &size);
1815 if (hr != D3D_OK) return D3D_OK;
1817 if (size < sizeof(D3DXSHADER_CONSTANTTABLE)) return D3D_OK;
1819 ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data;
1820 if (ctab_header->Size != sizeof(*ctab_header)) return D3D_OK;
1822 constant_info = (D3DXSHADER_CONSTANTINFO *)(data + ctab_header->ConstantInfo);
1823 for (i = 0; i < ctab_header->Constants; i++)
1825 const D3DXSHADER_TYPEINFO *type;
1827 TRACE("name = %s\n", data + constant_info[i].Name);
1829 type = (D3DXSHADER_TYPEINFO *)(data + constant_info[i].TypeInfo);
1831 if (type->Type == D3DXPT_SAMPLER
1832 || type->Type == D3DXPT_SAMPLER1D
1833 || type->Type == D3DXPT_SAMPLER2D
1834 || type->Type == D3DXPT_SAMPLER3D
1835 || type->Type == D3DXPT_SAMPLERCUBE)
1837 if (samplers) samplers[sampler_count] = data + constant_info[i].Name;
1839 ++sampler_count;
1843 TRACE("Found %u samplers\n", sampler_count);
1845 if (count) *count = sampler_count;
1847 return D3D_OK;