1 /*
2 * Copyright 2008 Luis Busquets
3 * Copyright 2009 Matteo Bruni
4 * Copyright 2011 Travis Athougies
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include "config.h"
22 #include "wine/port.h"
23
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"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
36
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);
42
43 LPCSTR WINAPI D3DXGetPixelShaderProfile(LPDIRECT3DDEVICE9 device)
44 {
45 D3DCAPS9 caps;
46
47 TRACE("device %p\n", device);
48
49 if (!device) return NULL;
50
51 IDirect3DDevice9_GetDeviceCaps(device,&caps);
52
53 switch (caps.PixelShaderVersion)
54 {
55 case D3DPS_VERSION(1, 1):
56 return "ps_1_1";
57
58 case D3DPS_VERSION(1, 2):
59 return "ps_1_2";
60
61 case D3DPS_VERSION(1, 3):
62 return "ps_1_3";
63
64 case D3DPS_VERSION(1, 4):
65 return "ps_1_4";
66
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))
74 {
75 return "ps_2_a";
76 }
77 if ((caps.PS20Caps.NumTemps>=32) &&
78 (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
79 {
80 return "ps_2_b";
81 }
82 return "ps_2_0";
83
84 case D3DPS_VERSION(3, 0):
85 return "ps_3_0";
86 }
87
88 return NULL;
89 }
90
91 UINT WINAPI D3DXGetShaderSize(const DWORD *byte_code)
92 {
93 const DWORD *ptr = byte_code;
94
95 TRACE("byte_code %p\n", byte_code);
96
97 if (!ptr) return 0;
98
99 /* Look for the END token, skipping the VERSION token */
100 while (*++ptr != D3DSIO_END)
101 {
102 /* Skip comments */
103 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
104 {
105 ptr += ((*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT);
106 }
107 }
108 ++ptr;
109
110 /* Return the shader size in bytes */
111 return (ptr - byte_code) * sizeof(*ptr);
112 }
113
114 DWORD WINAPI D3DXGetShaderVersion(const DWORD *byte_code)
115 {
116 TRACE("byte_code %p\n", byte_code);
117
118 return byte_code ? *byte_code : 0;
119 }
120
121 LPCSTR WINAPI D3DXGetVertexShaderProfile(LPDIRECT3DDEVICE9 device)
122 {
123 D3DCAPS9 caps;
124
125 TRACE("device %p\n", device);
126
127 if (!device) return NULL;
128
129 IDirect3DDevice9_GetDeviceCaps(device,&caps);
130
131 switch (caps.VertexShaderVersion)
132 {
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))
139 {
140 return "vs_2_a";
141 }
142 return "vs_2_0";
143 case D3DVS_VERSION(3, 0):
144 return "vs_3_0";
145 }
146
147 return NULL;
148 }
149
150 HRESULT WINAPI D3DXFindShaderComment(CONST DWORD* byte_code, DWORD fourcc, LPCVOID* data, UINT* size)
151 {
152 CONST DWORD *ptr = byte_code;
153
154 TRACE("(%p, %x, %p, %p)\n", byte_code, fourcc, data, size);
155
156 if (data) *data = NULL;
157 if (size) *size = 0;
158
159 if (!byte_code)
160 return D3DERR_INVALIDCALL;
161
162 while (*++ptr != D3DSIO_END)
163 {
164 /* Check if it is a comment */
165 if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
166 {
167 DWORD comment_size = (*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
168
169 /* Check if this is the comment we are looking for */
170 if (*(ptr + 1) == fourcc)
171 {
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;
180 }
181 ptr += comment_size;
182 }
183 }
184
185 return S_FALSE;
186 }
187
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)
195 {
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);
201
202 if(hr == E_FAIL) hr = D3DXERR_INVALIDDATA;
203 return hr;
204 }
205
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;
220
221 if(parent_data != NULL)
222 parent_name = *((const char **)parent_data - 1);
223
224 TRACE("Looking up for include file %s, parent %s\n", debugstr_a(filename), debugstr_a(parent_name));
225
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());
231
232 memcpy(pathname, parent_name, p - parent_name);
233 strcpy(pathname + (p - parent_name), filename);
234
235 file = CreateFileA(pathname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
236 if(file == INVALID_HANDLE_VALUE)
237 goto error;
238
239 TRACE("Include file found at pathname = %s\n", debugstr_a(pathname));
240
241 size = GetFileSize(file, NULL);
242 if(size == INVALID_FILE_SIZE)
243 goto error;
244
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;
251
252 *data = buffer + 1;
253
254 CloseHandle(file);
255 return S_OK;
256
257 error:
258 CloseHandle(file);
259 HeapFree(GetProcessHeap(), 0, pathname);
260 HeapFree(GetProcessHeap(), 0, buffer);
261 return HRESULT_FROM_WIN32(GetLastError());
262 }
263
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;
268 }
269
270 static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl = {
271 d3dincludefromfile_open,
272 d3dincludefromfile_close
273 };
274
275 struct D3DXIncludeImpl {
276 ID3DXInclude ID3DXInclude_iface;
277 };
278
279 HRESULT WINAPI D3DXAssembleShaderFromFileA(LPCSTR filename,
280 CONST D3DXMACRO* defines,
281 LPD3DXINCLUDE include,
282 DWORD flags,
283 LPD3DXBUFFER* shader,
284 LPD3DXBUFFER* error_messages)
285 {
286 LPWSTR filename_w = NULL;
287 DWORD len;
288 HRESULT ret;
289
290 if (!filename) return D3DXERR_INVALIDDATA;
291
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);
296
297 ret = D3DXAssembleShaderFromFileW(filename_w, defines, include, flags, shader, error_messages);
298
299 HeapFree(GetProcessHeap(), 0, filename_w);
300 return ret;
301 }
302
303 HRESULT WINAPI D3DXAssembleShaderFromFileW(LPCWSTR filename,
304 CONST D3DXMACRO* defines,
305 LPD3DXINCLUDE include,
306 DWORD flags,
307 LPD3DXBUFFER* shader,
308 LPD3DXBUFFER* error_messages)
309 {
310 void *buffer;
311 DWORD len;
312 HRESULT hr;
313 struct D3DXIncludeImpl includefromfile;
314
315 if(FAILED(map_view_of_file(filename, &buffer, &len)))
316 return D3DXERR_INVALIDDATA;
317
318 if(!include)
319 {
320 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
321 include = &includefromfile.ID3DXInclude_iface;
322 }
323
324 hr = D3DXAssembleShader(buffer, len, defines, include, flags,
325 shader, error_messages);
326
327 UnmapViewOfFile(buffer);
328 return hr;
329 }
330
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)
338 {
339 HRSRC res;
340 LPCSTR buffer;
341 DWORD len;
342
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);
349 }
350
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)
358 {
359 HRSRC res;
360 LPCSTR buffer;
361 DWORD len;
362
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);
369 }
370
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)
381 {
382 HRESULT hr = D3DCompile(pSrcData, srcDataLen, NULL,
383 (D3D_SHADER_MACRO *)pDefines, (ID3DInclude *)pInclude,
384 pFunctionName, pProfile, Flags, 0,
385 (ID3DBlob **)ppShader, (ID3DBlob **)ppErrorMsgs);
386
387 if(SUCCEEDED(hr) && ppConstantTable)
388 return D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*ppShader),
389 ppConstantTable);
390 return hr;
391 }
392
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)
402 {
403 LPWSTR filename_w = NULL;
404 DWORD len;
405 HRESULT ret;
406
407 if (!filename) return D3DXERR_INVALIDDATA;
408
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);
413
414 ret = D3DXCompileShaderFromFileW(filename_w, defines, include,
415 entrypoint, profile, flags,
416 shader, error_messages, constant_table);
417
418 HeapFree(GetProcessHeap(), 0, filename_w);
419 return ret;
420 }
421
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)
431 {
432 void *buffer;
433 DWORD len, filename_len;
434 HRESULT hr;
435 struct D3DXIncludeImpl includefromfile;
436 char *filename_a;
437
438 if (FAILED(map_view_of_file(filename, &buffer, &len)))
439 return D3DXERR_INVALIDDATA;
440
441 if (!include)
442 {
443 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
444 include = &includefromfile.ID3DXInclude_iface;
445 }
446
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)
450 {
451 UnmapViewOfFile(buffer);
452 return E_OUTOFMEMORY;
453 }
454 WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, filename_len, NULL, NULL);
455
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);
459
460 if (SUCCEEDED(hr) && constant_table)
461 hr = D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader),
462 constant_table);
463
464 HeapFree(GetProcessHeap(), 0, filename_a);
465 UnmapViewOfFile(buffer);
466 return hr;
467 }
468
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)
479 {
480 HRSRC res;
481 LPCSTR buffer;
482 DWORD len;
483
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);
490 }
491
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)
502 {
503 HRSRC res;
504 LPCSTR buffer;
505 DWORD len;
506
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);
513 }
514
515 HRESULT WINAPI D3DXPreprocessShader(LPCSTR data,
516 UINT data_len,
517 CONST D3DXMACRO* defines,
518 LPD3DXINCLUDE include,
519 LPD3DXBUFFER* shader,
520 LPD3DXBUFFER* error_messages)
521 {
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);
526 }
527
528 HRESULT WINAPI D3DXPreprocessShaderFromFileA(LPCSTR filename,
529 CONST D3DXMACRO* defines,
530 LPD3DXINCLUDE include,
531 LPD3DXBUFFER* shader,
532 LPD3DXBUFFER* error_messages)
533 {
534 WCHAR *filename_w = NULL;
535 DWORD len;
536 HRESULT ret;
537
538 if (!filename) return D3DXERR_INVALIDDATA;
539
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);
544
545 ret = D3DXPreprocessShaderFromFileW(filename_w, defines, include, shader, error_messages);
546
547 HeapFree(GetProcessHeap(), 0, filename_w);
548 return ret;
549 }
550
551 HRESULT WINAPI D3DXPreprocessShaderFromFileW(LPCWSTR filename,
552 CONST D3DXMACRO* defines,
553 LPD3DXINCLUDE include,
554 LPD3DXBUFFER* shader,
555 LPD3DXBUFFER* error_messages)
556 {
557 void *buffer;
558 DWORD len;
559 HRESULT hr;
560 struct D3DXIncludeImpl includefromfile;
561
562 if (FAILED(map_view_of_file(filename, &buffer, &len)))
563 return D3DXERR_INVALIDDATA;
564
565 if (!include)
566 {
567 includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
568 include = &includefromfile.ID3DXInclude_iface;
569 }
570
571 hr = D3DPreprocess(buffer, len, NULL,
572 (const D3D_SHADER_MACRO *)defines,
573 (ID3DInclude *) include,
574 (ID3DBlob **)shader, (ID3DBlob **)error_messages);
575
576 UnmapViewOfFile(buffer);
577 return hr;
578 }
579
580 HRESULT WINAPI D3DXPreprocessShaderFromResourceA(HMODULE module,
581 LPCSTR resource,
582 CONST D3DXMACRO* defines,
583 LPD3DXINCLUDE include,
584 LPD3DXBUFFER* shader,
585 LPD3DXBUFFER* error_messages)
586 {
587 HRSRC res;
588 const char *buffer;
589 DWORD len;
590
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);
597 }
598
599 HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module,
600 LPCWSTR resource,
601 CONST D3DXMACRO* defines,
602 LPD3DXINCLUDE include,
603 LPD3DXBUFFER* shader,
604 LPD3DXBUFFER* error_messages)
605 {
606 HRSRC res;
607 const char *buffer;
608 DWORD len;
609
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);
616
617 }
618
619 typedef struct ctab_constant {
620 D3DXCONSTANT_DESC desc;
621 struct ctab_constant *members;
622 } ctab_constant;
623
624 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl;
625
626 struct ID3DXConstantTableImpl {
627 ID3DXConstantTable ID3DXConstantTable_iface;
628 LONG ref;
629 char *ctab;
630 DWORD size;
631 D3DXCONSTANTTABLE_DESC desc;
632 ctab_constant *constants;
633 };
634
635 static void free_constant_table(struct ID3DXConstantTableImpl *table)
636 {
637 HeapFree(GetProcessHeap(), 0, table->constants);
638 HeapFree(GetProcessHeap(), 0, table->ctab);
639 }
640
641 static inline struct ID3DXConstantTableImpl *impl_from_ID3DXConstantTable(ID3DXConstantTable *iface)
642 {
643 return CONTAINING_RECORD(iface, struct ID3DXConstantTableImpl, ID3DXConstantTable_iface);
644 }
645
646 static inline int is_vertex_shader(DWORD version)
647 {
648 return (version & 0xFFFF0000) == 0xFFFE0000;
649 }
650
651 static DWORD calc_bytes(D3DXCONSTANT_DESC *desc)
652 {
653 if (desc->RegisterSet != D3DXRS_FLOAT4 && desc->RegisterSet != D3DXRS_SAMPLER)
654 FIXME("Don't know how to calculate Bytes for constants of type %d\n",
655 desc->RegisterSet);
656
657 return 4 * desc->Elements * desc->Rows * desc->Columns;
658 }
659
660 /*** IUnknown methods ***/
661 static HRESULT WINAPI ID3DXConstantTableImpl_QueryInterface(ID3DXConstantTable *iface, REFIID riid, void **out)
662 {
663 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
664
665 if (IsEqualGUID(riid, &IID_IUnknown) ||
666 IsEqualGUID(riid, &IID_ID3DXBuffer) ||
667 IsEqualGUID(riid, &IID_ID3DXConstantTable))
668 {
669 ID3DXConstantTable_AddRef(iface);
670 *out = iface;
671 return S_OK;
672 }
673
674 WARN("Interface %s not found.\n", debugstr_guid(riid));
675
676 return E_NOINTERFACE;
677 }
678
679 static ULONG WINAPI ID3DXConstantTableImpl_AddRef(ID3DXConstantTable *iface)
680 {
681 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
682
683 TRACE("(%p)->(): AddRef from %d\n", This, This->ref);
684
685 return InterlockedIncrement(&This->ref);
686 }
687
688 static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable *iface)
689 {
690 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
691 ULONG ref = InterlockedDecrement(&This->ref);
692
693 TRACE("(%p)->(): Release from %d\n", This, ref + 1);
694
695 if (!ref)
696 {
697 free_constant_table(This);
698 HeapFree(GetProcessHeap(), 0, This);
699 }
700
701 return ref;
702 }
703
704 /*** ID3DXBuffer methods ***/
705 static LPVOID WINAPI ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable *iface)
706 {
707 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
708
709 TRACE("(%p)->()\n", This);
710
711 return This->ctab;
712 }
713
714 static DWORD WINAPI ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable *iface)
715 {
716 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
717
718 TRACE("(%p)->()\n", This);
719
720 return This->size;
721 }
722
723 /*** ID3DXConstantTable methods ***/
724 static HRESULT WINAPI ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable *iface, D3DXCONSTANTTABLE_DESC *desc)
725 {
726 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
727
728 TRACE("(%p)->(%p)\n", This, desc);
729
730 if (!desc)
731 return D3DERR_INVALIDCALL;
732
733 memcpy(desc, &This->desc, sizeof(This->desc));
734
735 return D3D_OK;
736 }
737
738 static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable *iface, D3DXHANDLE constant,
739 D3DXCONSTANT_DESC *desc, UINT *count)
740 {
741 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
742 ctab_constant *constant_info;
743
744 TRACE("(%p)->(%p, %p, %p)\n", This, constant, desc, count);
745
746 if (!constant)
747 return D3DERR_INVALIDCALL;
748
749 /* Applications can pass the name of the constant in place of the handle */
750 if (!((UINT_PTR)constant >> 16))
751 constant_info = &This->constants[(UINT_PTR)constant - 1];
752 else
753 {
754 D3DXHANDLE c = ID3DXConstantTable_GetConstantByName(iface, NULL, constant);
755 if (!c)
756 return D3DERR_INVALIDCALL;
757
758 constant_info = &This->constants[(UINT_PTR)c - 1];
759 }
760
761 if (desc)
762 *desc = constant_info->desc;
763 if (count)
764 *count = 1;
765
766 return D3D_OK;
767 }
768
769 static UINT WINAPI ID3DXConstantTableImpl_GetSamplerIndex(ID3DXConstantTable *iface, D3DXHANDLE constant)
770 {
771 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
772 D3DXCONSTANT_DESC desc;
773 UINT count = 1;
774 HRESULT res;
775
776 TRACE("(%p)->(%p)\n", This, constant);
777
778 res = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &count);
779 if (FAILED(res))
780 return (UINT)-1;
781
782 if (desc.RegisterSet != D3DXRS_SAMPLER)
783 return (UINT)-1;
784
785 return desc.RegisterIndex;
786 }
787
788 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable *iface, D3DXHANDLE constant, UINT index)
789 {
790 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
791
792 TRACE("(%p)->(%p, %d)\n", This, constant, index);
793
794 if (constant)
795 {
796 FIXME("Only top level constants supported\n");
797 return NULL;
798 }
799
800 if (index >= This->desc.Constants)
801 return NULL;
802
803 return (D3DXHANDLE)(DWORD_PTR)(index + 1);
804 }
805
806 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable *iface, D3DXHANDLE constant, LPCSTR name)
807 {
808 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
809 UINT i;
810
811 TRACE("(%p)->(%p, %s)\n", This, constant, name);
812
813 if (!name)
814 return NULL;
815
816 if (constant)
817 {
818 FIXME("Only top level constants supported\n");
819 return NULL;
820 }
821
822 for (i = 0; i < This->desc.Constants; i++)
823 if (!strcmp(This->constants[i].desc.Name, name))
824 return (D3DXHANDLE)(DWORD_PTR)(i + 1);
825
826 return NULL;
827 }
828
829 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable *iface, D3DXHANDLE constant, UINT index)
830 {
831 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
832
833 FIXME("(%p)->(%p, %d): stub\n", This, constant, index);
834
835 return NULL;
836 }
837
838 static HRESULT set_float_array(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device, D3DXHANDLE constant, const void *data,
839 UINT count, D3DXPARAMETER_TYPE type)
840 {
841 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
842 D3DXCONSTANT_DESC desc;
843 HRESULT hr;
844 UINT i, desc_count = 1;
845 float row[4] = {0.0f, 0.0f, 0.0f, 0.0f};
846
847 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
848 if (FAILED(hr))
849 {
850 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
851 return D3DERR_INVALIDCALL;
852 }
853
854 switch (desc.RegisterSet)
855 {
856 case D3DXRS_FLOAT4:
857 for (i = 0; i < count && i < desc.RegisterCount; i++)
858 {
859 /* We need the for loop since each IDirect3DDevice9_Set*ShaderConstantF expects a float4 */
860 switch(type)
861 {
862 case D3DXPT_FLOAT:
863 row[0] = ((float *)data)[i];
864 break;
865 case D3DXPT_INT:
866 row[0] = (float)((int *)data)[i];
867 break;
868 default:
869 FIXME("Unhandled type passed to set_float_array\n");
870 return D3DERR_INVALIDCALL;
871 }
872 if (is_vertex_shader(This->desc.Version))
873 IDirect3DDevice9_SetVertexShaderConstantF(device, desc.RegisterIndex + i, row, 1);
874 else
875 IDirect3DDevice9_SetPixelShaderConstantF(device, desc.RegisterIndex + i, row, 1);
876 }
877 break;
878 default:
879 FIXME("Handle other register sets\n");
880 return E_NOTIMPL;
881 }
882
883 return D3D_OK;
884 }
885
886 static HRESULT WINAPI ID3DXConstantTableImpl_SetDefaults(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device)
887 {
888 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
889
890 FIXME("(%p)->(%p): stub\n", This, device);
891
892 return E_NOTIMPL;
893 }
894
895 static HRESULT WINAPI ID3DXConstantTableImpl_SetValue(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
896 D3DXHANDLE constant, LPCVOID data, UINT bytes)
897 {
898 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
899
900 FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, data, bytes);
901
902 return E_NOTIMPL;
903 }
904
905 static HRESULT WINAPI ID3DXConstantTableImpl_SetBool(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
906 D3DXHANDLE constant, BOOL b)
907 {
908 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
909
910 FIXME("(%p)->(%p, %p, %d): stub\n", This, device, constant, b);
911
912 return E_NOTIMPL;
913 }
914
915 static HRESULT WINAPI ID3DXConstantTableImpl_SetBoolArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
916 D3DXHANDLE constant, CONST BOOL* b, UINT count)
917 {
918 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
919
920 FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, b, count);
921
922 return E_NOTIMPL;
923 }
924
925 static HRESULT WINAPI ID3DXConstantTableImpl_SetInt(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device, D3DXHANDLE constant, INT n)
926 {
927 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
928
929 TRACE("(%p)->(%p, %p, %d)\n", This, device, constant, n);
930
931 return ID3DXConstantTable_SetIntArray(iface, device, constant, &n, 1);
932 }
933
934 static HRESULT WINAPI ID3DXConstantTableImpl_SetIntArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
935 D3DXHANDLE constant, CONST INT* n, UINT count)
936 {
937 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
938
939 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, n, count);
940
941 return set_float_array(iface, device, constant, n, count, D3DXPT_INT);
942 }
943
944 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloat(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
945 D3DXHANDLE constant, FLOAT f)
946 {
947 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
948
949 TRACE("(%p)->(%p, %p, %f)\n", This, device, constant, f);
950
951 return ID3DXConstantTable_SetFloatArray(iface, device, constant, &f, 1);
952 }
953
954 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloatArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
955 D3DXHANDLE constant, CONST FLOAT *f, UINT count)
956 {
957 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
958
959 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, f, count);
960
961 return set_float_array(iface, device, constant, f, count, D3DXPT_FLOAT);
962 }
963
964 static HRESULT WINAPI ID3DXConstantTableImpl_SetVector(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
965 D3DXHANDLE constant, CONST D3DXVECTOR4 *vector)
966 {
967 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
968
969 TRACE("(%p)->(%p, %p, %p)\n", This, device, constant, vector);
970
971 return ID3DXConstantTable_SetVectorArray(iface, device, constant, vector, 1);
972 }
973
974 static HRESULT WINAPI ID3DXConstantTableImpl_SetVectorArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
975 D3DXHANDLE constant, CONST D3DXVECTOR4 *vector, UINT count)
976 {
977 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
978 D3DXCONSTANT_DESC desc;
979 HRESULT hr;
980 UINT desc_count = 1;
981
982 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, vector, count);
983
984 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
985 if (FAILED(hr))
986 {
987 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
988 return D3DERR_INVALIDCALL;
989 }
990
991 switch (desc.RegisterSet)
992 {
993 case D3DXRS_FLOAT4:
994 if (is_vertex_shader(This->desc.Version))
995 IDirect3DDevice9_SetVertexShaderConstantF(device, desc.RegisterIndex, (float *)vector,
996 min(desc.RegisterCount, count));
997 else
998 IDirect3DDevice9_SetPixelShaderConstantF(device, desc.RegisterIndex, (float *)vector,
999 min(desc.RegisterCount, count));
1000 break;
1001 default:
1002 FIXME("Handle other register sets\n");
1003 return E_NOTIMPL;
1004 }
1005
1006 return D3D_OK;
1007 }
1008
1009 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrix(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
1010 D3DXHANDLE constant, CONST D3DXMATRIX *matrix)
1011 {
1012 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1013
1014 TRACE("(%p)->(%p, %p, %p)\n", This, device, constant, matrix);
1015
1016 return ID3DXConstantTable_SetMatrixArray(iface, device, constant, matrix, 1);
1017 }
1018
1019 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
1020 D3DXHANDLE constant, CONST D3DXMATRIX *matrix, UINT count)
1021 {
1022 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1023
1024 D3DXCONSTANT_DESC desc;
1025 HRESULT hr;
1026 UINT i, desc_count = 1;
1027 D3DXMATRIX temp;
1028
1029 TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, matrix, count);
1030
1031 hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
1032 if (FAILED(hr))
1033 {
1034 TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
1035 return D3DERR_INVALIDCALL;
1036 }
1037
1038 switch (desc.RegisterSet)
1039 {
1040 case D3DXRS_FLOAT4:
1041 /* i * 4 + 3 is the last register we set. The conditional makes sure that we don't access
1042 registers we're not supposed to */
1043 for (i = 0; i < count && i * 4 + 3 < desc.RegisterCount; i++)
1044 {
1045 if (desc.Class == D3DXPC_MATRIX_ROWS)
1046 temp = matrix[i];
1047 else
1048 D3DXMatrixTranspose(&temp, &matrix[i]);
1049
1050 if (is_vertex_shader(This->desc.Version))
1051 IDirect3DDevice9_SetVertexShaderConstantF(device, desc.RegisterIndex + i * 4, &temp.u.s._11, 4);
1052 else
1053 IDirect3DDevice9_SetPixelShaderConstantF(device, desc.RegisterIndex + i * 4, &temp.u.s._11, 4);
1054 }
1055 break;
1056 default:
1057 FIXME("Handle other register sets\n");
1058 return E_NOTIMPL;
1059 }
1060
1061 return D3D_OK;
1062 }
1063
1064 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixPointerArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
1065 D3DXHANDLE constant, CONST D3DXMATRIX **matrix, UINT count)
1066 {
1067 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1068
1069 FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
1070
1071 return E_NOTIMPL;
1072 }
1073
1074 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTranspose(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
1075 D3DXHANDLE constant, CONST D3DXMATRIX *matrix)
1076 {
1077 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1078
1079 FIXME("(%p)->(%p, %p, %p): stub\n", This, device, constant, matrix);
1080
1081 return E_NOTIMPL;
1082 }
1083
1084 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposeArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
1085 D3DXHANDLE constant, CONST D3DXMATRIX *matrix, UINT count)
1086 {
1087 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1088
1089 FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
1090
1091 return E_NOTIMPL;
1092 }
1093
1094 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposePointerArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
1095 D3DXHANDLE constant, CONST D3DXMATRIX **matrix, UINT count)
1096 {
1097 struct ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1098
1099 FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
1100
1101 return E_NOTIMPL;
1102 }
1103
1104 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl =
1105 {
1106 /*** IUnknown methods ***/
1107 ID3DXConstantTableImpl_QueryInterface,
1108 ID3DXConstantTableImpl_AddRef,
1109 ID3DXConstantTableImpl_Release,
1110 /*** ID3DXBuffer methods ***/
1111 ID3DXConstantTableImpl_GetBufferPointer,
1112 ID3DXConstantTableImpl_GetBufferSize,
1113 /*** ID3DXConstantTable methods ***/
1114 ID3DXConstantTableImpl_GetDesc,
1115 ID3DXConstantTableImpl_GetConstantDesc,
1116 ID3DXConstantTableImpl_GetSamplerIndex,
1117 ID3DXConstantTableImpl_GetConstant,
1118 ID3DXConstantTableImpl_GetConstantByName,
1119 ID3DXConstantTableImpl_GetConstantElement,
1120 ID3DXConstantTableImpl_SetDefaults,
1121 ID3DXConstantTableImpl_SetValue,
1122 ID3DXConstantTableImpl_SetBool,
1123 ID3DXConstantTableImpl_SetBoolArray,
1124 ID3DXConstantTableImpl_SetInt,
1125 ID3DXConstantTableImpl_SetIntArray,
1126 ID3DXConstantTableImpl_SetFloat,
1127 ID3DXConstantTableImpl_SetFloatArray,
1128 ID3DXConstantTableImpl_SetVector,
1129 ID3DXConstantTableImpl_SetVectorArray,
1130 ID3DXConstantTableImpl_SetMatrix,
1131 ID3DXConstantTableImpl_SetMatrixArray,
1132 ID3DXConstantTableImpl_SetMatrixPointerArray,
1133 ID3DXConstantTableImpl_SetMatrixTranspose,
1134 ID3DXConstantTableImpl_SetMatrixTransposeArray,
1135 ID3DXConstantTableImpl_SetMatrixTransposePointerArray
1136 };
1137
1138 static HRESULT parse_ctab_constant_type(const D3DXSHADER_TYPEINFO *type, ctab_constant *constant)
1139 {
1140 constant->desc.Class = type->Class;
1141 constant->desc.Type = type->Type;
1142 constant->desc.Rows = type->Rows;
1143 constant->desc.Columns = type->Columns;
1144 constant->desc.Elements = type->Elements;
1145 constant->desc.StructMembers = type->StructMembers;
1146 constant->desc.Bytes = calc_bytes(&constant->desc);
1147
1148 TRACE("class = %d, type = %d, rows = %d, columns = %d, elements = %d, struct_members = %d\n",
1149 constant->desc.Class, constant->desc.Type, constant->desc.Rows,
1150 constant->desc.Columns, constant->desc.Elements, constant->desc.StructMembers);
1151
1152 if ((constant->desc.Class == D3DXPC_STRUCT) && constant->desc.StructMembers)
1153 {
1154 FIXME("Struct not supported yet\n");
1155 return E_NOTIMPL;
1156 }
1157
1158 return D3D_OK;
1159 }
1160
1161 HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD *byte_code,
1162 DWORD flags,
1163 LPD3DXCONSTANTTABLE *constant_table)
1164 {
1165 struct ID3DXConstantTableImpl *object = NULL;
1166 HRESULT hr;
1167 LPCVOID data;
1168 UINT size;
1169 const D3DXSHADER_CONSTANTTABLE* ctab_header;
1170 D3DXSHADER_CONSTANTINFO* constant_info;
1171 DWORD i;
1172
1173 TRACE("(%p, %x, %p)\n", byte_code, flags, constant_table);
1174
1175 if (!byte_code || !constant_table)
1176 {
1177 WARN("Invalid argument specified.\n");
1178 return D3DERR_INVALIDCALL;
1179 }
1180
1181 hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), &data, &size);
1182 if (hr != D3D_OK)
1183 {
1184 WARN("CTAB not found.\n");
1185 return D3DXERR_INVALIDDATA;
1186 }
1187
1188 if (size < sizeof(D3DXSHADER_CONSTANTTABLE))
1189 {
1190 WARN("Invalid CTAB size.\n");
1191 return D3DXERR_INVALIDDATA;
1192 }
1193
1194 ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data;
1195 if (ctab_header->Size != sizeof(D3DXSHADER_CONSTANTTABLE))
1196 {
1197 WARN("Invalid D3DXSHADER_CONSTANTTABLE size.\n");
1198 return D3DXERR_INVALIDDATA;
1199 }
1200
1201 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1202 if (!object)
1203 {
1204 ERR("Out of memory\n");
1205 return E_OUTOFMEMORY;
1206 }
1207
1208 object->ID3DXConstantTable_iface.lpVtbl = &ID3DXConstantTable_Vtbl;
1209 object->ref = 1;
1210
1211 object->ctab = HeapAlloc(GetProcessHeap(), 0, size);
1212 if (!object->ctab)
1213 {
1214 ERR("Out of memory\n");
1215 HeapFree(GetProcessHeap(), 0, object);
1216 return E_OUTOFMEMORY;
1217 }
1218 object->size = size;
1219 memcpy(object->ctab, data, object->size);
1220
1221 object->desc.Creator = ctab_header->Creator ? object->ctab + ctab_header->Creator : NULL;
1222 object->desc.Version = ctab_header->Version;
1223 object->desc.Constants = ctab_header->Constants;
1224 TRACE("Creator %s, Version %x, Constants %u, Target %s\n",
1225 debugstr_a(object->desc.Creator), object->desc.Version, object->desc.Constants,
1226 debugstr_a(ctab_header->Target ? object->ctab + ctab_header->Target : NULL));
1227
1228 if (object->desc.Constants > 65535)
1229 {
1230 FIXME("Too many constants (%u)\n", object->desc.Constants);
1231 hr = E_NOTIMPL;
1232 goto error;
1233 }
1234
1235 object->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1236 sizeof(*object->constants) * object->desc.Constants);
1237 if (!object->constants)
1238 {
1239 ERR("Out of memory\n");
1240 hr = E_OUTOFMEMORY;
1241 goto error;
1242 }
1243
1244 constant_info = (LPD3DXSHADER_CONSTANTINFO)(object->ctab + ctab_header->ConstantInfo);
1245 for (i = 0; i < ctab_header->Constants; i++)
1246 {
1247 TRACE("name = %s\n", object->ctab + constant_info[i].Name);
1248 object->constants[i].desc.Name = object->ctab + constant_info[i].Name;
1249 object->constants[i].desc.RegisterSet = constant_info[i].RegisterSet;
1250 object->constants[i].desc.RegisterIndex = constant_info[i].RegisterIndex;
1251 object->constants[i].desc.RegisterCount = constant_info[i].RegisterCount;
1252 object->constants[i].desc.DefaultValue = object->ctab + constant_info[i].DefaultValue;
1253
1254 hr = parse_ctab_constant_type((LPD3DXSHADER_TYPEINFO)(object->ctab + constant_info[i].TypeInfo),
1255 &object->constants[i]);
1256 if (hr != D3D_OK)
1257 goto error;
1258 }
1259
1260 *constant_table = &object->ID3DXConstantTable_iface;
1261
1262 return D3D_OK;
1263
1264 error:
1265
1266 free_constant_table(object);
1267 HeapFree(GetProcessHeap(), 0, object);
1268
1269 return hr;
1270 }
1271
1272 HRESULT WINAPI D3DXGetShaderConstantTable(CONST DWORD* byte_code,
1273 LPD3DXCONSTANTTABLE* constant_table)
1274 {
1275 TRACE("(%p, %p): Forwarded to D3DXGetShaderConstantTableEx\n", byte_code, constant_table);
1276
1277 return D3DXGetShaderConstantTableEx(byte_code, 0, constant_table);
1278 }
1279
1280 HRESULT WINAPI D3DXGetShaderSamplers(CONST DWORD *byte_code, LPCSTR *samplers, UINT *count)
1281 {
1282 HRESULT hr;
1283 UINT i, sampler_count = 0;
1284 UINT size;
1285 LPCSTR data;
1286 const D3DXSHADER_CONSTANTTABLE *ctab_header;
1287 const D3DXSHADER_CONSTANTINFO *constant_info;
1288
1289 TRACE("byte_code %p, samplers %p, count %p\n", byte_code, samplers, count);
1290
1291 if (count) *count = 0;
1292
1293 hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), (LPCVOID *)&data, &size);
1294 if (hr != D3D_OK) return D3D_OK;
1295
1296 if (size < sizeof(D3DXSHADER_CONSTANTTABLE)) return D3D_OK;
1297
1298 ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data;
1299 if (ctab_header->Size != sizeof(*ctab_header)) return D3D_OK;
1300
1301 constant_info = (D3DXSHADER_CONSTANTINFO *)(data + ctab_header->ConstantInfo);
1302 for (i = 0; i < ctab_header->Constants; i++)
1303 {
1304 const D3DXSHADER_TYPEINFO *type;
1305
1306 TRACE("name = %s\n", data + constant_info[i].Name);
1307
1308 type = (D3DXSHADER_TYPEINFO *)(data + constant_info[i].TypeInfo);
1309
1310 if (type->Type == D3DXPT_SAMPLER
1311 || type->Type == D3DXPT_SAMPLER1D
1312 || type->Type == D3DXPT_SAMPLER2D
1313 || type->Type == D3DXPT_SAMPLER3D
1314 || type->Type == D3DXPT_SAMPLERCUBE)
1315 {
1316 if (samplers) samplers[sampler_count] = data + constant_info[i].Name;
1317
1318 ++sampler_count;
1319 }
1320 }
1321
1322 TRACE("Found %u samplers\n", sampler_count);
1323
1324 if (count) *count = sampler_count;
1325
1326 return D3D_OK;
1327 }
1328
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.