d3dx9: Use the variable instead of the type in HeapAlloc().
[wine] / dlls / d3dx9_36 / shader.c
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 (!byte_code)
157         return D3DERR_INVALIDCALL;
158
159     while (*++ptr != D3DSIO_END)
160     {
161         /* Check if it is a comment */
162         if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
163         {
164             DWORD comment_size = (*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
165
166             /* Check if this is the comment we are looking for */
167             if (*(ptr + 1) == fourcc)
168             {
169                 UINT ctab_size = (comment_size - 1) * sizeof(DWORD);
170                 LPCVOID ctab_data = ptr + 2;
171                 if (size)
172                     *size = ctab_size;
173                 if (data)
174                     *data = ctab_data;
175                 TRACE("Returning comment data at %p with size %d\n", ctab_data, ctab_size);
176                 return D3D_OK;
177             }
178             ptr += comment_size;
179         }
180     }
181
182     return S_FALSE;
183 }
184
185 HRESULT WINAPI D3DXAssembleShader(LPCSTR data,
186                                   UINT data_len,
187                                   CONST D3DXMACRO* defines,
188                                   LPD3DXINCLUDE include,
189                                   DWORD flags,
190                                   LPD3DXBUFFER* shader,
191                                   LPD3DXBUFFER* error_messages)
192 {
193     /* Forward to d3dcompiler: the parameter types aren't really different,
194        the actual data types are equivalent */
195     HRESULT hr = D3DAssemble(data, data_len, NULL, (D3D_SHADER_MACRO *)defines,
196                              (ID3DInclude *)include, flags, (ID3DBlob **)shader,
197                              (ID3DBlob **)error_messages);
198
199     if(hr == E_FAIL) hr = D3DXERR_INVALIDDATA;
200     return hr;
201 }
202
203 /* D3DXInclude private implementation, used to implement
204    D3DXAssembleShaderFromFile from D3DXAssembleShader */
205 /* To be able to correctly resolve include search paths we have to store
206    the pathname of each include file. We store the pathname pointer right
207    before the file data. */
208 static HRESULT WINAPI d3dincludefromfile_open(ID3DXInclude *iface,
209                                               D3DXINCLUDE_TYPE include_type,
210                                               LPCSTR filename, LPCVOID parent_data,
211                                               LPCVOID *data, UINT *bytes) {
212     const char *p, *parent_name = "";
213     char *pathname = NULL;
214     char **buffer = NULL;
215     HANDLE file;
216     UINT size;
217
218     if(parent_data != NULL)
219         parent_name = *((const char **)parent_data - 1);
220
221     TRACE("Looking up for include file %s, parent %s\n", debugstr_a(filename), debugstr_a(parent_name));
222
223     if ((p = strrchr(parent_name, '\\')) || (p = strrchr(parent_name, '/'))) p++;
224     else p = parent_name;
225     pathname = HeapAlloc(GetProcessHeap(), 0, (p - parent_name) + strlen(filename) + 1);
226     if(!pathname)
227         return HRESULT_FROM_WIN32(GetLastError());
228
229     memcpy(pathname, parent_name, p - parent_name);
230     strcpy(pathname + (p - parent_name), filename);
231
232     file = CreateFileA(pathname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
233     if(file == INVALID_HANDLE_VALUE)
234         goto error;
235
236     TRACE("Include file found at pathname = %s\n", debugstr_a(pathname));
237
238     size = GetFileSize(file, NULL);
239     if(size == INVALID_FILE_SIZE)
240         goto error;
241
242     buffer = HeapAlloc(GetProcessHeap(), 0, size + sizeof(char *));
243     if(!buffer)
244         goto error;
245     *buffer = pathname;
246     if(!ReadFile(file, buffer + 1, size, bytes, NULL))
247         goto error;
248
249     *data = buffer + 1;
250
251     CloseHandle(file);
252     return S_OK;
253
254 error:
255     CloseHandle(file);
256     HeapFree(GetProcessHeap(), 0, pathname);
257     HeapFree(GetProcessHeap(), 0, buffer);
258     return HRESULT_FROM_WIN32(GetLastError());
259 }
260
261 static HRESULT WINAPI d3dincludefromfile_close(ID3DXInclude *iface, LPCVOID data) {
262     HeapFree(GetProcessHeap(), 0, *((char **)data - 1));
263     HeapFree(GetProcessHeap(), 0, (char **)data - 1);
264     return S_OK;
265 }
266
267 static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl = {
268     d3dincludefromfile_open,
269     d3dincludefromfile_close
270 };
271
272 struct D3DXIncludeImpl {
273     ID3DXInclude ID3DXInclude_iface;
274 };
275
276 HRESULT WINAPI D3DXAssembleShaderFromFileA(LPCSTR filename,
277                                            CONST D3DXMACRO* defines,
278                                            LPD3DXINCLUDE include,
279                                            DWORD flags,
280                                            LPD3DXBUFFER* shader,
281                                            LPD3DXBUFFER* error_messages)
282 {
283     LPWSTR filename_w = NULL;
284     DWORD len;
285     HRESULT ret;
286
287     if (!filename) return D3DXERR_INVALIDDATA;
288
289     len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
290     filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
291     if (!filename_w) return E_OUTOFMEMORY;
292     MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
293
294     ret = D3DXAssembleShaderFromFileW(filename_w, defines, include, flags, shader, error_messages);
295
296     HeapFree(GetProcessHeap(), 0, filename_w);
297     return ret;
298 }
299
300 HRESULT WINAPI D3DXAssembleShaderFromFileW(LPCWSTR filename,
301                                            CONST D3DXMACRO* defines,
302                                            LPD3DXINCLUDE include,
303                                            DWORD flags,
304                                            LPD3DXBUFFER* shader,
305                                            LPD3DXBUFFER* error_messages)
306 {
307     void *buffer;
308     DWORD len;
309     HRESULT hr;
310     struct D3DXIncludeImpl includefromfile;
311
312     if(FAILED(map_view_of_file(filename, &buffer, &len)))
313         return D3DXERR_INVALIDDATA;
314
315     if(!include)
316     {
317         includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
318         include = &includefromfile.ID3DXInclude_iface;
319     }
320
321     hr = D3DXAssembleShader(buffer, len, defines, include, flags,
322                             shader, error_messages);
323
324     UnmapViewOfFile(buffer);
325     return hr;
326 }
327
328 HRESULT WINAPI D3DXAssembleShaderFromResourceA(HMODULE module,
329                                                LPCSTR resource,
330                                                CONST D3DXMACRO* defines,
331                                                LPD3DXINCLUDE include,
332                                                DWORD flags,
333                                                LPD3DXBUFFER* shader,
334                                                LPD3DXBUFFER* error_messages)
335 {
336     HRSRC res;
337     LPCSTR buffer;
338     DWORD len;
339
340     if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
341         return D3DXERR_INVALIDDATA;
342     if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
343         return D3DXERR_INVALIDDATA;
344     return D3DXAssembleShader(buffer, len, defines, include, flags,
345                               shader, error_messages);
346 }
347
348 HRESULT WINAPI D3DXAssembleShaderFromResourceW(HMODULE module,
349                                                LPCWSTR resource,
350                                                CONST D3DXMACRO* defines,
351                                                LPD3DXINCLUDE include,
352                                                DWORD flags,
353                                                LPD3DXBUFFER* shader,
354                                                LPD3DXBUFFER* error_messages)
355 {
356     HRSRC res;
357     LPCSTR buffer;
358     DWORD len;
359
360     if (!(res = FindResourceW(module, resource, (LPCWSTR)RT_RCDATA)))
361         return D3DXERR_INVALIDDATA;
362     if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
363         return D3DXERR_INVALIDDATA;
364     return D3DXAssembleShader(buffer, len, defines, include, flags,
365                               shader, error_messages);
366 }
367
368 HRESULT WINAPI D3DXCompileShader(LPCSTR pSrcData,
369                                  UINT srcDataLen,
370                                  CONST D3DXMACRO* pDefines,
371                                  LPD3DXINCLUDE pInclude,
372                                  LPCSTR pFunctionName,
373                                  LPCSTR pProfile,
374                                  DWORD Flags,
375                                  LPD3DXBUFFER* ppShader,
376                                  LPD3DXBUFFER* ppErrorMsgs,
377                                  LPD3DXCONSTANTTABLE * ppConstantTable)
378 {
379     HRESULT hr = D3DCompile(pSrcData, srcDataLen, NULL,
380                             (D3D_SHADER_MACRO *)pDefines, (ID3DInclude *)pInclude,
381                             pFunctionName, pProfile, Flags, 0,
382                             (ID3DBlob **)ppShader, (ID3DBlob **)ppErrorMsgs);
383
384     if(SUCCEEDED(hr) && ppConstantTable)
385         return D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*ppShader),
386                                           ppConstantTable);
387     return hr;
388 }
389
390 HRESULT WINAPI D3DXCompileShaderFromFileA(LPCSTR filename,
391                                           CONST D3DXMACRO* defines,
392                                           LPD3DXINCLUDE include,
393                                           LPCSTR entrypoint,
394                                           LPCSTR profile,
395                                           DWORD flags,
396                                           LPD3DXBUFFER* shader,
397                                           LPD3DXBUFFER* error_messages,
398                                           LPD3DXCONSTANTTABLE* constant_table)
399 {
400     LPWSTR filename_w = NULL;
401     DWORD len;
402     HRESULT ret;
403
404     if (!filename) return D3DXERR_INVALIDDATA;
405
406     len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
407     filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
408     if (!filename_w) return E_OUTOFMEMORY;
409     MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
410
411     ret = D3DXCompileShaderFromFileW(filename_w, defines, include,
412                                      entrypoint, profile, flags,
413                                      shader, error_messages, constant_table);
414
415     HeapFree(GetProcessHeap(), 0, filename_w);
416     return ret;
417 }
418
419 HRESULT WINAPI D3DXCompileShaderFromFileW(LPCWSTR filename,
420                                           CONST D3DXMACRO* defines,
421                                           LPD3DXINCLUDE include,
422                                           LPCSTR entrypoint,
423                                           LPCSTR profile,
424                                           DWORD flags,
425                                           LPD3DXBUFFER* shader,
426                                           LPD3DXBUFFER* error_messages,
427                                           LPD3DXCONSTANTTABLE* constant_table)
428 {
429     void *buffer;
430     DWORD len, filename_len;
431     HRESULT hr;
432     struct D3DXIncludeImpl includefromfile;
433     char *filename_a;
434
435     if (FAILED(map_view_of_file(filename, &buffer, &len)))
436         return D3DXERR_INVALIDDATA;
437
438     if (!include)
439     {
440         includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
441         include = &includefromfile.ID3DXInclude_iface;
442     }
443
444     filename_len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
445     filename_a = HeapAlloc(GetProcessHeap(), 0, filename_len * sizeof(char));
446     if (!filename_a)
447     {
448         UnmapViewOfFile(buffer);
449         return E_OUTOFMEMORY;
450     }
451     WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, filename_len, NULL, NULL);
452
453     hr = D3DCompile(buffer, len, filename_a, (const D3D_SHADER_MACRO *)defines,
454                     (ID3DInclude *)include, entrypoint, profile, flags, 0,
455                     (ID3DBlob **)shader, (ID3DBlob **)error_messages);
456
457     if (SUCCEEDED(hr) && constant_table)
458         hr = D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader),
459                                         constant_table);
460
461     HeapFree(GetProcessHeap(), 0, filename_a);
462     UnmapViewOfFile(buffer);
463     return hr;
464 }
465
466 HRESULT WINAPI D3DXCompileShaderFromResourceA(HMODULE module,
467                                               LPCSTR resource,
468                                               CONST D3DXMACRO* defines,
469                                               LPD3DXINCLUDE include,
470                                               LPCSTR entrypoint,
471                                               LPCSTR profile,
472                                               DWORD flags,
473                                               LPD3DXBUFFER* shader,
474                                               LPD3DXBUFFER* error_messages,
475                                               LPD3DXCONSTANTTABLE* constant_table)
476 {
477     HRSRC res;
478     LPCSTR buffer;
479     DWORD len;
480
481     if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
482         return D3DXERR_INVALIDDATA;
483     if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
484         return D3DXERR_INVALIDDATA;
485     return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
486                              flags, shader, error_messages, constant_table);
487 }
488
489 HRESULT WINAPI D3DXCompileShaderFromResourceW(HMODULE module,
490                                               LPCWSTR resource,
491                                               CONST D3DXMACRO* defines,
492                                               LPD3DXINCLUDE include,
493                                               LPCSTR entrypoint,
494                                               LPCSTR profile,
495                                               DWORD flags,
496                                               LPD3DXBUFFER* shader,
497                                               LPD3DXBUFFER* error_messages,
498                                               LPD3DXCONSTANTTABLE* constant_table)
499 {
500     HRSRC res;
501     LPCSTR buffer;
502     DWORD len;
503
504     if (!(res = FindResourceW(module, resource, (LPCWSTR)RT_RCDATA)))
505         return D3DXERR_INVALIDDATA;
506     if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
507         return D3DXERR_INVALIDDATA;
508     return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
509                              flags, shader, error_messages, constant_table);
510 }
511
512 HRESULT WINAPI D3DXPreprocessShader(LPCSTR data,
513                                     UINT data_len,
514                                     CONST D3DXMACRO* defines,
515                                     LPD3DXINCLUDE include,
516                                     LPD3DXBUFFER* shader,
517                                     LPD3DXBUFFER* error_messages)
518 {
519     TRACE("Forward to D3DPreprocess\n");
520     return D3DPreprocess(data, data_len, NULL,
521                          (const D3D_SHADER_MACRO *)defines, (ID3DInclude *)include,
522                          (ID3DBlob **)shader, (ID3DBlob **)error_messages);
523 }
524
525 HRESULT WINAPI D3DXPreprocessShaderFromFileA(LPCSTR filename,
526                                              CONST D3DXMACRO* defines,
527                                              LPD3DXINCLUDE include,
528                                              LPD3DXBUFFER* shader,
529                                              LPD3DXBUFFER* error_messages)
530 {
531     WCHAR *filename_w = NULL;
532     DWORD len;
533     HRESULT ret;
534
535     if (!filename) return D3DXERR_INVALIDDATA;
536
537     len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
538     filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
539     if (!filename_w) return E_OUTOFMEMORY;
540     MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
541
542     ret = D3DXPreprocessShaderFromFileW(filename_w, defines, include, shader, error_messages);
543
544     HeapFree(GetProcessHeap(), 0, filename_w);
545     return ret;
546 }
547
548 HRESULT WINAPI D3DXPreprocessShaderFromFileW(LPCWSTR filename,
549                                              CONST D3DXMACRO* defines,
550                                              LPD3DXINCLUDE include,
551                                              LPD3DXBUFFER* shader,
552                                              LPD3DXBUFFER* error_messages)
553 {
554     void *buffer;
555     DWORD len;
556     HRESULT hr;
557     struct D3DXIncludeImpl includefromfile;
558
559     if (FAILED(map_view_of_file(filename, &buffer, &len)))
560         return D3DXERR_INVALIDDATA;
561
562     if (!include)
563     {
564         includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
565         include = &includefromfile.ID3DXInclude_iface;
566     }
567
568     hr = D3DPreprocess(buffer, len, NULL,
569                        (const D3D_SHADER_MACRO *)defines,
570                        (ID3DInclude *) include,
571                        (ID3DBlob **)shader, (ID3DBlob **)error_messages);
572
573     UnmapViewOfFile(buffer);
574     return hr;
575 }
576
577 HRESULT WINAPI D3DXPreprocessShaderFromResourceA(HMODULE module,
578                                                  LPCSTR resource,
579                                                  CONST D3DXMACRO* defines,
580                                                  LPD3DXINCLUDE include,
581                                                  LPD3DXBUFFER* shader,
582                                                  LPD3DXBUFFER* error_messages)
583 {
584     HRSRC res;
585     const char *buffer;
586     DWORD len;
587
588     if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
589         return D3DXERR_INVALIDDATA;
590     if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
591         return D3DXERR_INVALIDDATA;
592     return D3DXPreprocessShader(buffer, len, defines, include,
593                                 shader, error_messages);
594 }
595
596 HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module,
597                                                  LPCWSTR resource,
598                                                  CONST D3DXMACRO* defines,
599                                                  LPD3DXINCLUDE include,
600                                                  LPD3DXBUFFER* shader,
601                                                  LPD3DXBUFFER* error_messages)
602 {
603     HRSRC res;
604     const char *buffer;
605     DWORD len;
606
607     if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
608         return D3DXERR_INVALIDDATA;
609     if (FAILED(load_resource_into_memory(module, res, (void **)&buffer, &len)))
610         return D3DXERR_INVALIDDATA;
611     return D3DXPreprocessShader(buffer, len, defines, include,
612                                 shader, error_messages);
613
614 }
615
616 typedef struct ctab_constant {
617     D3DXCONSTANT_DESC desc;
618     struct ctab_constant *members;
619 } ctab_constant;
620
621 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl;
622
623 typedef struct ID3DXConstantTableImpl {
624     ID3DXConstantTable ID3DXConstantTable_iface;
625     LONG ref;
626     char *ctab;
627     DWORD size;
628     D3DXCONSTANTTABLE_DESC desc;
629     ctab_constant *constants;
630 } ID3DXConstantTableImpl;
631
632 static inline ID3DXConstantTableImpl *impl_from_ID3DXConstantTable(ID3DXConstantTable *iface)
633 {
634     return CONTAINING_RECORD(iface, ID3DXConstantTableImpl, ID3DXConstantTable_iface);
635 }
636
637 static inline int is_vertex_shader(DWORD version)
638 {
639     return (version & 0xFFFF0000) == 0xFFFE0000;
640 }
641
642 static DWORD calc_bytes(D3DXCONSTANT_DESC *desc)
643 {
644     if (desc->RegisterSet != D3DXRS_FLOAT4 && desc->RegisterSet != D3DXRS_SAMPLER)
645         FIXME("Don't know how to calculate Bytes for constants of type %d\n",
646                 desc->RegisterSet);
647
648     return 4 * desc->Elements * desc->Rows * desc->Columns;
649 }
650
651 /*** IUnknown methods ***/
652 static HRESULT WINAPI ID3DXConstantTableImpl_QueryInterface(ID3DXConstantTable* iface, REFIID riid, void** ppvObject)
653 {
654     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
655
656     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
657
658     if (IsEqualGUID(riid, &IID_IUnknown) ||
659         IsEqualGUID(riid, &IID_ID3DXBuffer) ||
660         IsEqualGUID(riid, &IID_ID3DXConstantTable))
661     {
662         ID3DXConstantTable_AddRef(iface);
663         *ppvObject = This;
664         return S_OK;
665     }
666
667     WARN("Interface %s not found.\n", debugstr_guid(riid));
668
669     return E_NOINTERFACE;
670 }
671
672 static ULONG WINAPI ID3DXConstantTableImpl_AddRef(ID3DXConstantTable* iface)
673 {
674     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
675
676     TRACE("(%p)->(): AddRef from %d\n", This, This->ref);
677
678     return InterlockedIncrement(&This->ref);
679 }
680
681 static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable* iface)
682 {
683     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
684     ULONG ref = InterlockedDecrement(&This->ref);
685
686     TRACE("(%p)->(): Release from %d\n", This, ref + 1);
687
688     if (!ref)
689     {
690         HeapFree(GetProcessHeap(), 0, This->constants);
691         HeapFree(GetProcessHeap(), 0, This->ctab);
692         HeapFree(GetProcessHeap(), 0, This);
693     }
694
695     return ref;
696 }
697
698 /*** ID3DXBuffer methods ***/
699 static LPVOID WINAPI ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable* iface)
700 {
701     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
702
703     TRACE("(%p)->()\n", This);
704
705     return This->ctab;
706 }
707
708 static DWORD WINAPI ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable* iface)
709 {
710     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
711
712     TRACE("(%p)->()\n", This);
713
714     return This->size;
715 }
716
717 /*** ID3DXConstantTable methods ***/
718 static HRESULT WINAPI ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable* iface, D3DXCONSTANTTABLE_DESC *desc)
719 {
720     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
721
722     TRACE("(%p)->(%p)\n", This, desc);
723
724     if (!desc)
725         return D3DERR_INVALIDCALL;
726
727     memcpy(desc, &This->desc, sizeof(This->desc));
728
729     return D3D_OK;
730 }
731
732 static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable* iface, D3DXHANDLE constant,
733                                                              D3DXCONSTANT_DESC *desc, UINT *count)
734 {
735     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
736     ctab_constant *constant_info;
737
738     TRACE("(%p)->(%p, %p, %p)\n", This, constant, desc, count);
739
740     if (!constant)
741         return D3DERR_INVALIDCALL;
742
743     /* Applications can pass the name of the constant in place of the handle */
744     if (!((UINT_PTR)constant >> 16))
745         constant_info = &This->constants[(UINT_PTR)constant - 1];
746     else
747     {
748         D3DXHANDLE c = ID3DXConstantTable_GetConstantByName(iface, NULL, constant);
749         if (!c)
750             return D3DERR_INVALIDCALL;
751
752         constant_info = &This->constants[(UINT_PTR)c - 1];
753     }
754
755     if (desc)
756         *desc = constant_info->desc;
757     if (count)
758         *count = 1;
759
760     return D3D_OK;
761 }
762
763 static UINT WINAPI ID3DXConstantTableImpl_GetSamplerIndex(ID3DXConstantTable *iface, D3DXHANDLE constant)
764 {
765     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
766     D3DXCONSTANT_DESC desc;
767     UINT count = 1;
768     HRESULT res;
769
770     TRACE("(%p)->(%p)\n", This, constant);
771
772     res = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &count);
773     if (FAILED(res))
774         return (UINT)-1;
775
776     if (desc.RegisterSet != D3DXRS_SAMPLER)
777         return (UINT)-1;
778
779     return desc.RegisterIndex;
780 }
781
782 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable* iface, D3DXHANDLE constant, UINT index)
783 {
784     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
785
786     TRACE("(%p)->(%p, %d)\n", This, constant, index);
787
788     if (constant)
789     {
790         FIXME("Only top level constants supported\n");
791         return NULL;
792     }
793
794     if (index >= This->desc.Constants)
795         return NULL;
796
797     return (D3DXHANDLE)(DWORD_PTR)(index + 1);
798 }
799
800 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable* iface, D3DXHANDLE constant, LPCSTR name)
801 {
802     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
803     UINT i;
804
805     TRACE("(%p)->(%p, %s)\n", This, constant, name);
806
807     if (!name)
808         return NULL;
809
810     if (constant)
811     {
812         FIXME("Only top level constants supported\n");
813         return NULL;
814     }
815
816     for (i = 0; i < This->desc.Constants; i++)
817         if (!strcmp(This->constants[i].desc.Name, name))
818             return (D3DXHANDLE)(DWORD_PTR)(i + 1);
819
820     return NULL;
821 }
822
823 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable* iface, D3DXHANDLE constant, UINT index)
824 {
825     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
826
827     FIXME("(%p)->(%p, %d): stub\n", This, constant, index);
828
829     return NULL;
830 }
831
832 static HRESULT set_float_array(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device, D3DXHANDLE constant, const void *data,
833                                UINT count, D3DXPARAMETER_TYPE type)
834 {
835     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
836
837     D3DXCONSTANT_DESC desc;
838     HRESULT hr;
839     UINT i, desc_count = 1;
840     float row[4] = {0.0f, 0.0f, 0.0f, 0.0f};
841
842     hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
843     if (FAILED(hr))
844     {
845         TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
846         return D3DERR_INVALIDCALL;
847     }
848
849     switch (desc.RegisterSet)
850     {
851         case D3DXRS_FLOAT4:
852             for (i = 0; i < count && i < desc.RegisterCount; i++)
853             {
854                 /* We need the for loop since each IDirect3DDevice9_Set*ShaderConstantF expects a float4 */
855                 switch(type)
856                 {
857                     case D3DXPT_FLOAT:
858                         row[0] = ((float *)data)[i];
859                         break;
860                     case D3DXPT_INT:
861                         row[0] = (float)((int *)data)[i];
862                         break;
863                     default:
864                         FIXME("Unhandled type passed to set_float_array\n");
865                         return D3DERR_INVALIDCALL;
866                 }
867                 if (is_vertex_shader(This->desc.Version))
868                     IDirect3DDevice9_SetVertexShaderConstantF(device, desc.RegisterIndex + i, row, 1);
869                 else
870                     IDirect3DDevice9_SetPixelShaderConstantF(device, desc.RegisterIndex + i, row, 1);
871             }
872             break;
873         default:
874             FIXME("Handle other register sets\n");
875             return E_NOTIMPL;
876     }
877
878     return D3D_OK;
879 }
880
881 static HRESULT WINAPI ID3DXConstantTableImpl_SetDefaults(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device)
882 {
883     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
884
885     FIXME("(%p)->(%p): stub\n", This, device);
886
887     return E_NOTIMPL;
888 }
889
890 static HRESULT WINAPI ID3DXConstantTableImpl_SetValue(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
891                                                       D3DXHANDLE constant, LPCVOID data, UINT bytes)
892 {
893     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
894
895     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, data, bytes);
896
897     return E_NOTIMPL;
898 }
899
900 static HRESULT WINAPI ID3DXConstantTableImpl_SetBool(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
901                                                      D3DXHANDLE constant, BOOL b)
902 {
903     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
904
905     FIXME("(%p)->(%p, %p, %d): stub\n", This, device, constant, b);
906
907     return E_NOTIMPL;
908 }
909
910 static HRESULT WINAPI ID3DXConstantTableImpl_SetBoolArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
911                                                           D3DXHANDLE constant, CONST BOOL* b, UINT count)
912 {
913     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
914
915     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, b, count);
916
917     return E_NOTIMPL;
918 }
919
920 static HRESULT WINAPI ID3DXConstantTableImpl_SetInt(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device, D3DXHANDLE constant, INT n)
921 {
922     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
923
924     TRACE("(%p)->(%p, %p, %d)\n", This, device, constant, n);
925
926     return ID3DXConstantTable_SetIntArray(iface, device, constant, &n, 1);
927 }
928
929 static HRESULT WINAPI ID3DXConstantTableImpl_SetIntArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
930                                                          D3DXHANDLE constant, CONST INT* n, UINT count)
931 {
932     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
933
934     TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, n, count);
935
936     return set_float_array(iface, device, constant, n, count, D3DXPT_INT);
937 }
938
939 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloat(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
940                                                       D3DXHANDLE constant, FLOAT f)
941 {
942     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
943
944     TRACE("(%p)->(%p, %p, %f)\n", This, device, constant, f);
945
946     return ID3DXConstantTable_SetFloatArray(iface, device, constant, &f, 1);
947 }
948
949 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloatArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
950                                                            D3DXHANDLE constant, CONST FLOAT *f, UINT count)
951 {
952     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
953
954     TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, f, count);
955
956     return set_float_array(iface, device, constant, f, count, D3DXPT_FLOAT);
957 }
958
959 static HRESULT WINAPI ID3DXConstantTableImpl_SetVector(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
960                                                        D3DXHANDLE constant, CONST D3DXVECTOR4 *vector)
961 {
962     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
963
964     TRACE("(%p)->(%p, %p, %p)\n", This, device, constant, vector);
965
966     return ID3DXConstantTable_SetVectorArray(iface, device, constant, vector, 1);
967 }
968
969 static HRESULT WINAPI ID3DXConstantTableImpl_SetVectorArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
970                                                             D3DXHANDLE constant, CONST D3DXVECTOR4 *vector, UINT count)
971 {
972     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
973
974     D3DXCONSTANT_DESC desc;
975     HRESULT hr;
976     UINT desc_count = 1;
977
978     TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, vector, count);
979
980     hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
981     if (FAILED(hr))
982     {
983         TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
984         return D3DERR_INVALIDCALL;
985     }
986
987     switch (desc.RegisterSet)
988     {
989         case D3DXRS_FLOAT4:
990             if (is_vertex_shader(This->desc.Version))
991                 IDirect3DDevice9_SetVertexShaderConstantF(device, desc.RegisterIndex, (float *)vector,
992                         min(desc.RegisterCount, count));
993             else
994                 IDirect3DDevice9_SetPixelShaderConstantF(device, desc.RegisterIndex, (float *)vector,
995                         min(desc.RegisterCount, count));
996             break;
997         default:
998             FIXME("Handle other register sets\n");
999             return E_NOTIMPL;
1000     }
1001
1002     return D3D_OK;
1003 }
1004
1005 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrix(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
1006                                                        D3DXHANDLE constant, CONST D3DXMATRIX *matrix)
1007 {
1008     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1009
1010     TRACE("(%p)->(%p, %p, %p)\n", This, device, constant, matrix);
1011
1012     return ID3DXConstantTable_SetMatrixArray(iface, device, constant, matrix, 1);
1013 }
1014
1015 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixArray(ID3DXConstantTable *iface, LPDIRECT3DDEVICE9 device,
1016                                                             D3DXHANDLE constant, CONST D3DXMATRIX *matrix, UINT count)
1017 {
1018     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1019
1020     D3DXCONSTANT_DESC desc;
1021     HRESULT hr;
1022     UINT i, desc_count = 1;
1023     D3DXMATRIX temp;
1024
1025     TRACE("(%p)->(%p, %p, %p, %d)\n", This, device, constant, matrix, count);
1026
1027     hr = ID3DXConstantTable_GetConstantDesc(iface, constant, &desc, &desc_count);
1028     if (FAILED(hr))
1029     {
1030         TRACE("ID3DXConstantTable_GetConstantDesc failed: %08x\n", hr);
1031         return D3DERR_INVALIDCALL;
1032     }
1033
1034     switch (desc.RegisterSet)
1035     {
1036         case D3DXRS_FLOAT4:
1037             /* i * 4 + 3 is the last register we set. The conditional makes sure that we don't access
1038                registers we're not supposed to */
1039             for (i = 0; i < count && i * 4 + 3 < desc.RegisterCount; i++)
1040             {
1041                 if (desc.Class == D3DXPC_MATRIX_ROWS)
1042                     temp = matrix[i];
1043                 else
1044                     D3DXMatrixTranspose(&temp, &matrix[i]);
1045
1046                 if (is_vertex_shader(This->desc.Version))
1047                     IDirect3DDevice9_SetVertexShaderConstantF(device, desc.RegisterIndex + i * 4, &temp.u.s._11, 4);
1048                 else
1049                     IDirect3DDevice9_SetPixelShaderConstantF(device, desc.RegisterIndex + i * 4, &temp.u.s._11, 4);
1050             }
1051             break;
1052         default:
1053             FIXME("Handle other register sets\n");
1054             return E_NOTIMPL;
1055     }
1056
1057     return D3D_OK;
1058 }
1059
1060 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixPointerArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
1061                                                                    D3DXHANDLE constant, CONST D3DXMATRIX** matrix, UINT count)
1062 {
1063     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1064
1065     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
1066
1067     return E_NOTIMPL;
1068 }
1069
1070 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTranspose(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
1071                                                                 D3DXHANDLE constant, CONST D3DXMATRIX* matrix)
1072 {
1073     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1074
1075     FIXME("(%p)->(%p, %p, %p): stub\n", This, device, constant, matrix);
1076
1077     return E_NOTIMPL;
1078 }
1079
1080 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposeArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
1081                                                                      D3DXHANDLE constant, CONST D3DXMATRIX* matrix, UINT count)
1082 {
1083     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1084
1085     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
1086
1087     return E_NOTIMPL;
1088 }
1089
1090 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposePointerArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
1091                                                                             D3DXHANDLE constant, CONST D3DXMATRIX** matrix, UINT count)
1092 {
1093     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
1094
1095     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
1096
1097     return E_NOTIMPL;
1098 }
1099
1100 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl =
1101 {
1102     /*** IUnknown methods ***/
1103     ID3DXConstantTableImpl_QueryInterface,
1104     ID3DXConstantTableImpl_AddRef,
1105     ID3DXConstantTableImpl_Release,
1106     /*** ID3DXBuffer methods ***/
1107     ID3DXConstantTableImpl_GetBufferPointer,
1108     ID3DXConstantTableImpl_GetBufferSize,
1109     /*** ID3DXConstantTable methods ***/
1110     ID3DXConstantTableImpl_GetDesc,
1111     ID3DXConstantTableImpl_GetConstantDesc,
1112     ID3DXConstantTableImpl_GetSamplerIndex,
1113     ID3DXConstantTableImpl_GetConstant,
1114     ID3DXConstantTableImpl_GetConstantByName,
1115     ID3DXConstantTableImpl_GetConstantElement,
1116     ID3DXConstantTableImpl_SetDefaults,
1117     ID3DXConstantTableImpl_SetValue,
1118     ID3DXConstantTableImpl_SetBool,
1119     ID3DXConstantTableImpl_SetBoolArray,
1120     ID3DXConstantTableImpl_SetInt,
1121     ID3DXConstantTableImpl_SetIntArray,
1122     ID3DXConstantTableImpl_SetFloat,
1123     ID3DXConstantTableImpl_SetFloatArray,
1124     ID3DXConstantTableImpl_SetVector,
1125     ID3DXConstantTableImpl_SetVectorArray,
1126     ID3DXConstantTableImpl_SetMatrix,
1127     ID3DXConstantTableImpl_SetMatrixArray,
1128     ID3DXConstantTableImpl_SetMatrixPointerArray,
1129     ID3DXConstantTableImpl_SetMatrixTranspose,
1130     ID3DXConstantTableImpl_SetMatrixTransposeArray,
1131     ID3DXConstantTableImpl_SetMatrixTransposePointerArray
1132 };
1133
1134 static HRESULT parse_ctab_constant_type(const D3DXSHADER_TYPEINFO *type, ctab_constant *constant)
1135 {
1136     constant->desc.Class = type->Class;
1137     constant->desc.Type = type->Type;
1138     constant->desc.Rows = type->Rows;
1139     constant->desc.Columns = type->Columns;
1140     constant->desc.Elements = type->Elements;
1141     constant->desc.StructMembers = type->StructMembers;
1142     constant->desc.Bytes = calc_bytes(&constant->desc);
1143
1144     TRACE("class = %d, type = %d, rows = %d, columns = %d, elements = %d, struct_members = %d\n",
1145           constant->desc.Class, constant->desc.Type, constant->desc.Elements,
1146           constant->desc.Rows, constant->desc.Columns, constant->desc.StructMembers);
1147
1148     if ((constant->desc.Class == D3DXPC_STRUCT) && constant->desc.StructMembers)
1149     {
1150         FIXME("Struct not supported yet\n");
1151         return E_NOTIMPL;
1152     }
1153
1154     return D3D_OK;
1155 }
1156
1157 HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code,
1158                                             DWORD flags,
1159                                             LPD3DXCONSTANTTABLE* constant_table)
1160 {
1161     ID3DXConstantTableImpl* object = NULL;
1162     HRESULT hr;
1163     LPCVOID data;
1164     UINT size;
1165     const D3DXSHADER_CONSTANTTABLE* ctab_header;
1166     D3DXSHADER_CONSTANTINFO* constant_info;
1167     DWORD i;
1168
1169     TRACE("(%p, %x, %p)\n", byte_code, flags, constant_table);
1170
1171     if (!byte_code || !constant_table)
1172         return D3DERR_INVALIDCALL;
1173
1174     hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), &data, &size);
1175     if (hr != D3D_OK)
1176         return D3DXERR_INVALIDDATA;
1177
1178     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1179     if (!object)
1180     {
1181         ERR("Out of memory\n");
1182         return E_OUTOFMEMORY;
1183     }
1184
1185     object->ID3DXConstantTable_iface.lpVtbl = &ID3DXConstantTable_Vtbl;
1186     object->ref = 1;
1187
1188     if (size < sizeof(D3DXSHADER_CONSTANTTABLE))
1189     {
1190         hr = D3DXERR_INVALIDDATA;
1191         goto error;
1192     }
1193
1194     object->ctab = HeapAlloc(GetProcessHeap(), 0, size);
1195     if (!object->ctab)
1196     {
1197         ERR("Out of memory\n");
1198         hr = E_OUTOFMEMORY;
1199         goto error;
1200     }
1201     object->size = size;
1202     memcpy(object->ctab, data, object->size);
1203
1204     ctab_header = (const D3DXSHADER_CONSTANTTABLE*)data;
1205     if (ctab_header->Size != sizeof(D3DXSHADER_CONSTANTTABLE))
1206     {
1207         hr = D3DXERR_INVALIDDATA;
1208         goto error;
1209     }
1210     object->desc.Creator = ctab_header->Creator ? object->ctab + ctab_header->Creator : NULL;
1211     object->desc.Version = ctab_header->Version;
1212     object->desc.Constants = ctab_header->Constants;
1213     if (object->desc.Creator)
1214         TRACE("Creator = %s\n", object->desc.Creator);
1215     TRACE("Version = %x\n", object->desc.Version);
1216     TRACE("Constants = %d\n", ctab_header->Constants);
1217     if (ctab_header->Target)
1218         TRACE("Target = %s\n", object->ctab + ctab_header->Target);
1219
1220     if (object->desc.Constants > 65535)
1221     {
1222         FIXME("Too many constants (%u)\n", object->desc.Constants);
1223         hr = E_NOTIMPL;
1224         goto error;
1225     }
1226
1227     object->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1228                                   sizeof(*object->constants) * object->desc.Constants);
1229     if (!object->constants)
1230     {
1231          ERR("Out of memory\n");
1232          hr = E_OUTOFMEMORY;
1233          goto error;
1234     }
1235
1236     constant_info = (LPD3DXSHADER_CONSTANTINFO)(object->ctab + ctab_header->ConstantInfo);
1237     for (i = 0; i < ctab_header->Constants; i++)
1238     {
1239         TRACE("name = %s\n", object->ctab + constant_info[i].Name);
1240         object->constants[i].desc.Name = object->ctab + constant_info[i].Name;
1241         object->constants[i].desc.RegisterSet = constant_info[i].RegisterSet;
1242         object->constants[i].desc.RegisterIndex = constant_info[i].RegisterIndex;
1243         object->constants[i].desc.RegisterCount = constant_info[i].RegisterCount;
1244         object->constants[i].desc.DefaultValue = object->ctab + constant_info[i].DefaultValue;
1245
1246         hr = parse_ctab_constant_type((LPD3DXSHADER_TYPEINFO)(object->ctab + constant_info[i].TypeInfo),
1247              &object->constants[i]);
1248         if (hr != D3D_OK)
1249             goto error;
1250     }
1251
1252     *constant_table = &object->ID3DXConstantTable_iface;
1253
1254     return D3D_OK;
1255
1256 error:
1257
1258     HeapFree(GetProcessHeap(), 0, object->constants);
1259     HeapFree(GetProcessHeap(), 0, object->ctab);
1260     HeapFree(GetProcessHeap(), 0, object);
1261
1262     return hr;
1263 }
1264
1265 HRESULT WINAPI D3DXGetShaderConstantTable(CONST DWORD* byte_code,
1266                                           LPD3DXCONSTANTTABLE* constant_table)
1267 {
1268     TRACE("(%p, %p): Forwarded to D3DXGetShaderConstantTableEx\n", byte_code, constant_table);
1269
1270     return D3DXGetShaderConstantTableEx(byte_code, 0, constant_table);
1271 }
1272
1273 HRESULT WINAPI D3DXGetShaderSamplers(CONST DWORD *byte_code, LPCSTR *samplers, UINT *count)
1274 {
1275     HRESULT hr;
1276     UINT i, sampler_count = 0;
1277     UINT size;
1278     LPCSTR data;
1279     const D3DXSHADER_CONSTANTTABLE *ctab_header;
1280     const D3DXSHADER_CONSTANTINFO *constant_info;
1281
1282     TRACE("byte_code %p, samplers %p, count %p\n", byte_code, samplers, count);
1283
1284     if (count) *count = 0;
1285
1286     hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), (LPCVOID *)&data, &size);
1287     if (hr != D3D_OK) return D3D_OK;
1288
1289     if (size < sizeof(D3DXSHADER_CONSTANTTABLE)) return D3D_OK;
1290
1291     ctab_header = (const D3DXSHADER_CONSTANTTABLE *)data;
1292     if (ctab_header->Size != sizeof(*ctab_header)) return D3D_OK;
1293
1294     constant_info = (D3DXSHADER_CONSTANTINFO *)(data + ctab_header->ConstantInfo);
1295     for (i = 0; i < ctab_header->Constants; i++)
1296     {
1297         const D3DXSHADER_TYPEINFO *type;
1298
1299         TRACE("name = %s\n", data + constant_info[i].Name);
1300
1301         type = (D3DXSHADER_TYPEINFO *)(data + constant_info[i].TypeInfo);
1302
1303         if (type->Type == D3DXPT_SAMPLER
1304                 || type->Type == D3DXPT_SAMPLER1D
1305                 || type->Type == D3DXPT_SAMPLER2D
1306                 || type->Type == D3DXPT_SAMPLER3D
1307                 || type->Type == D3DXPT_SAMPLERCUBE)
1308         {
1309             if (samplers) samplers[sampler_count] = data + constant_info[i].Name;
1310
1311             ++sampler_count;
1312         }
1313     }
1314
1315     TRACE("Found %u samplers\n", sampler_count);
1316
1317     if (count) *count = sampler_count;
1318
1319     return D3D_OK;
1320 }