msi/tests: Prevent a popup on Windows NT.
[wine] / dlls / d3dx9_36 / shader.c
1 /*
2  * Copyright 2008 Luis Busquets
3  * Copyright 2009 Matteo Bruni
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 #include "config.h"
21 #include "wine/port.h"
22 #include "wine/debug.h"
23 #include "wine/unicode.h"
24 #include "windef.h"
25 #include "wingdi.h"
26 #include "objbase.h"
27 #include "d3dcommon.h"
28 #include "d3dcompiler.h"
29 #include "d3dx9_36_private.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
32
33 /* This function is not declared in the SDK headers yet */
34 HRESULT WINAPI D3DAssemble(LPCVOID data, SIZE_T datasize, LPCSTR filename,
35                            const D3D_SHADER_MACRO *defines, ID3DInclude *include,
36                            UINT flags,
37                            ID3DBlob **shader, ID3DBlob **error_messages);
38
39 LPCSTR WINAPI D3DXGetPixelShaderProfile(LPDIRECT3DDEVICE9 device)
40 {
41     D3DCAPS9 caps;
42
43     TRACE("device %p\n", device);
44
45     if (!device) return NULL;
46
47     IDirect3DDevice9_GetDeviceCaps(device,&caps);
48
49     switch (caps.PixelShaderVersion)
50     {
51     case D3DPS_VERSION(1, 1):
52         return "ps_1_1";
53
54     case D3DPS_VERSION(1, 2):
55         return "ps_1_2";
56
57     case D3DPS_VERSION(1, 3):
58         return "ps_1_3";
59
60     case D3DPS_VERSION(1, 4):
61         return "ps_1_4";
62
63     case D3DPS_VERSION(2, 0):
64         if ((caps.PS20Caps.NumTemps>=22)                          &&
65             (caps.PS20Caps.Caps&D3DPS20CAPS_ARBITRARYSWIZZLE)     &&
66             (caps.PS20Caps.Caps&D3DPS20CAPS_GRADIENTINSTRUCTIONS) &&
67             (caps.PS20Caps.Caps&D3DPS20CAPS_PREDICATION)          &&
68             (caps.PS20Caps.Caps&D3DPS20CAPS_NODEPENDENTREADLIMIT) &&
69             (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
70         {
71             return "ps_2_a";
72         }
73         if ((caps.PS20Caps.NumTemps>=32)                          &&
74             (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
75         {
76             return "ps_2_b";
77         }
78         return "ps_2_0";
79
80     case D3DPS_VERSION(3, 0):
81         return "ps_3_0";
82     }
83
84     return NULL;
85 }
86
87 UINT WINAPI D3DXGetShaderSize(const DWORD *byte_code)
88 {
89     const DWORD *ptr = byte_code;
90
91     TRACE("byte_code %p\n", byte_code);
92
93     if (!ptr) return 0;
94
95     /* Look for the END token, skipping the VERSION token */
96     while (*++ptr != D3DSIO_END)
97     {
98         /* Skip comments */
99         if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
100         {
101             ptr += ((*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT);
102         }
103     }
104     ++ptr;
105
106     /* Return the shader size in bytes */
107     return (ptr - byte_code) * sizeof(*ptr);
108 }
109
110 DWORD WINAPI D3DXGetShaderVersion(const DWORD *byte_code)
111 {
112     TRACE("byte_code %p\n", byte_code);
113
114     return byte_code ? *byte_code : 0;
115 }
116
117 LPCSTR WINAPI D3DXGetVertexShaderProfile(LPDIRECT3DDEVICE9 device)
118 {
119     D3DCAPS9 caps;
120
121     TRACE("device %p\n", device);
122
123     if (!device) return NULL;
124
125     IDirect3DDevice9_GetDeviceCaps(device,&caps);
126
127     switch (caps.VertexShaderVersion)
128     {
129     case D3DVS_VERSION(1, 1):
130         return "vs_1_1";
131     case D3DVS_VERSION(2, 0):
132         if ((caps.VS20Caps.NumTemps>=13) &&
133             (caps.VS20Caps.DynamicFlowControlDepth==24) &&
134             (caps.VS20Caps.Caps&D3DPS20CAPS_PREDICATION))
135         {
136             return "vs_2_a";
137         }
138         return "vs_2_0";
139     case D3DVS_VERSION(3, 0):
140         return "vs_3_0";
141     }
142
143     return NULL;
144 }
145
146 HRESULT WINAPI D3DXFindShaderComment(CONST DWORD* byte_code, DWORD fourcc, LPCVOID* data, UINT* size)
147 {
148     CONST DWORD *ptr = byte_code;
149
150     TRACE("(%p, %x, %p, %p)\n", byte_code, fourcc, data, size);
151
152     if (!byte_code)
153         return D3DERR_INVALIDCALL;
154
155     while (*++ptr != D3DSIO_END)
156     {
157         /* Check if it is a comment */
158         if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
159         {
160             DWORD comment_size = (*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
161
162             /* Check if this is the comment we are looking for */
163             if (*(ptr + 1) == fourcc)
164             {
165                 UINT ctab_size = (comment_size - 1) * sizeof(DWORD);
166                 LPCVOID ctab_data = ptr + 2;
167                 if (size)
168                     *size = ctab_size;
169                 if (data)
170                     *data = ctab_data;
171                 TRACE("Returning comment data at %p with size %d\n", ctab_data, ctab_size);
172                 return D3D_OK;
173             }
174             ptr += comment_size;
175         }
176     }
177
178     return S_FALSE;
179 }
180
181 HRESULT WINAPI D3DXAssembleShader(LPCSTR data,
182                                   UINT data_len,
183                                   CONST D3DXMACRO* defines,
184                                   LPD3DXINCLUDE include,
185                                   DWORD flags,
186                                   LPD3DXBUFFER* shader,
187                                   LPD3DXBUFFER* error_messages)
188 {
189     /* Forward to d3dcompiler: the parameter types aren't really different,
190        the actual data types are equivalent */
191     HRESULT hr = D3DAssemble(data, data_len, NULL, (D3D_SHADER_MACRO *)defines,
192                              (ID3DInclude *)include, flags, (ID3DBlob **)shader,
193                              (ID3DBlob **)error_messages);
194
195     if(hr == E_FAIL) hr = D3DXERR_INVALIDDATA;
196     return hr;
197 }
198
199 /* D3DXInclude private implementation, used to implement
200    D3DXAssembleShaderFromFile from D3DXAssembleShader */
201 /* To be able to correctly resolve include search paths we have to store
202    the pathname of each include file. We store the pathname pointer right
203    before the file data. */
204 static HRESULT WINAPI d3dincludefromfile_open(ID3DXInclude *iface,
205                                               D3DXINCLUDE_TYPE include_type,
206                                               LPCSTR filename, LPCVOID parent_data,
207                                               LPCVOID *data, UINT *bytes) {
208     const char *p, *parent_name = "";
209     char *pathname = NULL;
210     char **buffer = NULL;
211     HANDLE file;
212     UINT size;
213
214     if(parent_data != NULL)
215         parent_name = *((const char **)parent_data - 1);
216
217     TRACE("Looking up for include file %s, parent %s\n", debugstr_a(filename), debugstr_a(parent_name));
218
219     if ((p = strrchr(parent_name, '\\')) || (p = strrchr(parent_name, '/'))) p++;
220     else p = parent_name;
221     pathname = HeapAlloc(GetProcessHeap(), 0, (p - parent_name) + strlen(filename) + 1);
222     if(!pathname)
223         return HRESULT_FROM_WIN32(GetLastError());
224
225     memcpy(pathname, parent_name, p - parent_name);
226     strcpy(pathname + (p - parent_name), filename);
227
228     file = CreateFileA(pathname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
229     if(file == INVALID_HANDLE_VALUE)
230         goto error;
231
232     TRACE("Include file found at pathname = %s\n", debugstr_a(pathname));
233
234     size = GetFileSize(file, NULL);
235     if(size == INVALID_FILE_SIZE)
236         goto error;
237
238     buffer = HeapAlloc(GetProcessHeap(), 0, size + sizeof(char *));
239     if(!buffer)
240         goto error;
241     *buffer = pathname;
242     if(!ReadFile(file, buffer + 1, size, bytes, NULL))
243         goto error;
244
245     *data = buffer + 1;
246
247     CloseHandle(file);
248     return S_OK;
249
250 error:
251     CloseHandle(file);
252     HeapFree(GetProcessHeap(), 0, pathname);
253     HeapFree(GetProcessHeap(), 0, buffer);
254     return HRESULT_FROM_WIN32(GetLastError());
255 }
256
257 static HRESULT WINAPI d3dincludefromfile_close(ID3DXInclude *iface, LPCVOID data) {
258     HeapFree(GetProcessHeap(), 0, *((char **)data - 1));
259     HeapFree(GetProcessHeap(), 0, (char **)data - 1);
260     return S_OK;
261 }
262
263 static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl = {
264     d3dincludefromfile_open,
265     d3dincludefromfile_close
266 };
267
268 struct D3DXIncludeImpl {
269     const ID3DXIncludeVtbl *lpVtbl;
270 };
271
272 HRESULT WINAPI D3DXAssembleShaderFromFileA(LPCSTR filename,
273                                            CONST D3DXMACRO* defines,
274                                            LPD3DXINCLUDE include,
275                                            DWORD flags,
276                                            LPD3DXBUFFER* shader,
277                                            LPD3DXBUFFER* error_messages)
278 {
279     LPWSTR filename_w = NULL;
280     DWORD len;
281     HRESULT ret;
282
283     if (!filename) return D3DXERR_INVALIDDATA;
284
285     len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
286     filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
287     if (!filename_w) return E_OUTOFMEMORY;
288     MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
289
290     ret = D3DXAssembleShaderFromFileW(filename_w, defines, include, flags, shader, error_messages);
291
292     HeapFree(GetProcessHeap(), 0, filename_w);
293     return ret;
294 }
295
296 HRESULT WINAPI D3DXAssembleShaderFromFileW(LPCWSTR filename,
297                                            CONST D3DXMACRO* defines,
298                                            LPD3DXINCLUDE include,
299                                            DWORD flags,
300                                            LPD3DXBUFFER* shader,
301                                            LPD3DXBUFFER* error_messages)
302 {
303     void *buffer;
304     DWORD len;
305     HRESULT hr;
306     struct D3DXIncludeImpl includefromfile;
307
308     if(FAILED(map_view_of_file(filename, &buffer, &len)))
309         return D3DXERR_INVALIDDATA;
310
311     if(!include)
312     {
313         includefromfile.lpVtbl = &D3DXInclude_Vtbl;
314         include = (LPD3DXINCLUDE)&includefromfile;
315     }
316
317     hr = D3DXAssembleShader(buffer, len, defines, include, flags,
318                             shader, error_messages);
319
320     UnmapViewOfFile(buffer);
321     return hr;
322 }
323
324 HRESULT WINAPI D3DXAssembleShaderFromResourceA(HMODULE module,
325                                                LPCSTR resource,
326                                                CONST D3DXMACRO* defines,
327                                                LPD3DXINCLUDE include,
328                                                DWORD flags,
329                                                LPD3DXBUFFER* shader,
330                                                LPD3DXBUFFER* error_messages)
331 {
332     HRSRC res;
333     LPCSTR buffer;
334     DWORD len;
335
336     if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
337         return D3DXERR_INVALIDDATA;
338     if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
339         return D3DXERR_INVALIDDATA;
340     return D3DXAssembleShader(buffer, len, defines, include, flags,
341                               shader, error_messages);
342 }
343
344 HRESULT WINAPI D3DXAssembleShaderFromResourceW(HMODULE module,
345                                                LPCWSTR resource,
346                                                CONST D3DXMACRO* defines,
347                                                LPD3DXINCLUDE include,
348                                                DWORD flags,
349                                                LPD3DXBUFFER* shader,
350                                                LPD3DXBUFFER* error_messages)
351 {
352     HRSRC res;
353     LPCSTR buffer;
354     DWORD len;
355
356     if (!(res = FindResourceW(module, resource, (LPCWSTR)RT_RCDATA)))
357         return D3DXERR_INVALIDDATA;
358     if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
359         return D3DXERR_INVALIDDATA;
360     return D3DXAssembleShader(buffer, len, defines, include, flags,
361                               shader, error_messages);
362 }
363
364 HRESULT WINAPI D3DXCompileShader(LPCSTR pSrcData,
365                                  UINT srcDataLen,
366                                  CONST D3DXMACRO* pDefines,
367                                  LPD3DXINCLUDE pInclude,
368                                  LPCSTR pFunctionName,
369                                  LPCSTR pProfile,
370                                  DWORD Flags,
371                                  LPD3DXBUFFER* ppShader,
372                                  LPD3DXBUFFER* ppErrorMsgs,
373                                  LPD3DXCONSTANTTABLE * ppConstantTable)
374 {
375     HRESULT hr = D3DCompile(pSrcData, srcDataLen, NULL,
376                             (D3D_SHADER_MACRO *)pDefines, (ID3DInclude *)pInclude,
377                             pFunctionName, pProfile, Flags, 0,
378                             (ID3DBlob **)ppShader, (ID3DBlob **)ppErrorMsgs);
379
380     if(SUCCEEDED(hr) && ppConstantTable)
381         return D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*ppShader),
382                                           ppConstantTable);
383     return hr;
384 }
385
386 HRESULT WINAPI D3DXCompileShaderFromFileA(LPCSTR filename,
387                                           CONST D3DXMACRO* defines,
388                                           LPD3DXINCLUDE include,
389                                           LPCSTR entrypoint,
390                                           LPCSTR profile,
391                                           DWORD flags,
392                                           LPD3DXBUFFER* shader,
393                                           LPD3DXBUFFER* error_messages,
394                                           LPD3DXCONSTANTTABLE* constant_table)
395 {
396     LPWSTR filename_w = NULL;
397     DWORD len;
398     HRESULT ret;
399
400     if (!filename) return D3DXERR_INVALIDDATA;
401
402     len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
403     filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
404     if (!filename_w) return E_OUTOFMEMORY;
405     MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
406
407     ret = D3DXCompileShaderFromFileW(filename_w, defines, include,
408                                      entrypoint, profile, flags,
409                                      shader, error_messages, constant_table);
410
411     HeapFree(GetProcessHeap(), 0, filename_w);
412     return ret;
413 }
414
415 HRESULT WINAPI D3DXCompileShaderFromFileW(LPCWSTR filename,
416                                           CONST D3DXMACRO* defines,
417                                           LPD3DXINCLUDE include,
418                                           LPCSTR entrypoint,
419                                           LPCSTR profile,
420                                           DWORD flags,
421                                           LPD3DXBUFFER* shader,
422                                           LPD3DXBUFFER* error_messages,
423                                           LPD3DXCONSTANTTABLE* constant_table)
424 {
425     void *buffer;
426     DWORD len, filename_len;
427     HRESULT hr;
428     struct D3DXIncludeImpl includefromfile;
429     char *filename_a;
430
431     if (FAILED(map_view_of_file(filename, &buffer, &len)))
432         return D3DXERR_INVALIDDATA;
433
434     if (!include)
435     {
436         includefromfile.lpVtbl = &D3DXInclude_Vtbl;
437         include = (LPD3DXINCLUDE)&includefromfile;
438     }
439
440     filename_len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
441     filename_a = HeapAlloc(GetProcessHeap(), 0, filename_len * sizeof(char));
442     if (!filename_a)
443     {
444         UnmapViewOfFile(buffer);
445         return E_OUTOFMEMORY;
446     }
447     WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, filename_len, NULL, NULL);
448
449     hr = D3DCompile(buffer, len, filename_a, (const D3D_SHADER_MACRO *)defines,
450                     (ID3DInclude *)include, entrypoint, profile, flags, 0,
451                     (ID3DBlob **)shader, (ID3DBlob **)error_messages);
452
453     if (SUCCEEDED(hr) && constant_table)
454         hr = D3DXGetShaderConstantTable(ID3DXBuffer_GetBufferPointer(*shader),
455                                         constant_table);
456
457     HeapFree(GetProcessHeap(), 0, filename_a);
458     UnmapViewOfFile(buffer);
459     return hr;
460 }
461
462 HRESULT WINAPI D3DXCompileShaderFromResourceA(HMODULE module,
463                                               LPCSTR resource,
464                                               CONST D3DXMACRO* defines,
465                                               LPD3DXINCLUDE include,
466                                               LPCSTR entrypoint,
467                                               LPCSTR profile,
468                                               DWORD flags,
469                                               LPD3DXBUFFER* shader,
470                                               LPD3DXBUFFER* error_messages,
471                                               LPD3DXCONSTANTTABLE* constant_table)
472 {
473     HRSRC res;
474     LPCSTR buffer;
475     DWORD len;
476
477     if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
478         return D3DXERR_INVALIDDATA;
479     if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
480         return D3DXERR_INVALIDDATA;
481     return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
482                              flags, shader, error_messages, constant_table);
483 }
484
485 HRESULT WINAPI D3DXCompileShaderFromResourceW(HMODULE module,
486                                               LPCWSTR resource,
487                                               CONST D3DXMACRO* defines,
488                                               LPD3DXINCLUDE include,
489                                               LPCSTR entrypoint,
490                                               LPCSTR profile,
491                                               DWORD flags,
492                                               LPD3DXBUFFER* shader,
493                                               LPD3DXBUFFER* error_messages,
494                                               LPD3DXCONSTANTTABLE* constant_table)
495 {
496     HRSRC res;
497     LPCSTR buffer;
498     DWORD len;
499
500     if (!(res = FindResourceW(module, resource, (LPCWSTR)RT_RCDATA)))
501         return D3DXERR_INVALIDDATA;
502     if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
503         return D3DXERR_INVALIDDATA;
504     return D3DXCompileShader(buffer, len, defines, include, entrypoint, profile,
505                              flags, shader, error_messages, constant_table);
506 }
507
508 HRESULT WINAPI D3DXPreprocessShader(LPCSTR data,
509                                     UINT data_len,
510                                     CONST D3DXMACRO* defines,
511                                     LPD3DXINCLUDE include,
512                                     LPD3DXBUFFER* shader,
513                                     LPD3DXBUFFER* error_messages)
514 {
515     TRACE("Forward to D3DPreprocess\n");
516     return D3DPreprocess(data, data_len, NULL,
517                          (const D3D_SHADER_MACRO *)defines, (ID3DInclude *)include,
518                          (ID3DBlob **)shader, (ID3DBlob **)error_messages);
519 }
520
521 HRESULT WINAPI D3DXPreprocessShaderFromFileA(LPCSTR filename,
522                                              CONST D3DXMACRO* defines,
523                                              LPD3DXINCLUDE include,
524                                              LPD3DXBUFFER* shader,
525                                              LPD3DXBUFFER* error_messages)
526 {
527     WCHAR *filename_w = NULL;
528     DWORD len;
529     HRESULT ret;
530
531     if (!filename) return D3DXERR_INVALIDDATA;
532
533     len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
534     filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
535     if (!filename_w) return E_OUTOFMEMORY;
536     MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
537
538     ret = D3DXPreprocessShaderFromFileW(filename_w, defines, include, shader, error_messages);
539
540     HeapFree(GetProcessHeap(), 0, filename_w);
541     return ret;
542 }
543
544 HRESULT WINAPI D3DXPreprocessShaderFromFileW(LPCWSTR filename,
545                                              CONST D3DXMACRO* defines,
546                                              LPD3DXINCLUDE include,
547                                              LPD3DXBUFFER* shader,
548                                              LPD3DXBUFFER* error_messages)
549 {
550     void *buffer;
551     DWORD len;
552     HRESULT hr;
553     struct D3DXIncludeImpl includefromfile;
554
555     if (FAILED(map_view_of_file(filename, &buffer, &len)))
556         return D3DXERR_INVALIDDATA;
557
558     if (!include)
559     {
560         includefromfile.lpVtbl = &D3DXInclude_Vtbl;
561         include = (LPD3DXINCLUDE)&includefromfile;
562     }
563
564     hr = D3DPreprocess(buffer, len, NULL,
565                        (const D3D_SHADER_MACRO *)defines,
566                        (ID3DInclude *) include,
567                        (ID3DBlob **)shader, (ID3DBlob **)error_messages);
568
569     UnmapViewOfFile(buffer);
570     return hr;
571 }
572
573 HRESULT WINAPI D3DXPreprocessShaderFromResourceA(HMODULE module,
574                                                  LPCSTR resource,
575                                                  CONST D3DXMACRO* defines,
576                                                  LPD3DXINCLUDE include,
577                                                  LPD3DXBUFFER* shader,
578                                                  LPD3DXBUFFER* error_messages)
579 {
580     HRSRC res;
581     const char *buffer;
582     DWORD len;
583
584     if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
585         return D3DXERR_INVALIDDATA;
586     if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
587         return D3DXERR_INVALIDDATA;
588     return D3DXPreprocessShader(buffer, len, defines, include,
589                                 shader, error_messages);
590 }
591
592 HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module,
593                                                  LPCWSTR resource,
594                                                  CONST D3DXMACRO* defines,
595                                                  LPD3DXINCLUDE include,
596                                                  LPD3DXBUFFER* shader,
597                                                  LPD3DXBUFFER* error_messages)
598 {
599     HRSRC res;
600     const char *buffer;
601     DWORD len;
602
603     if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
604         return D3DXERR_INVALIDDATA;
605     if (FAILED(load_resource_into_memory(module, res, (void **)&buffer, &len)))
606         return D3DXERR_INVALIDDATA;
607     return D3DXPreprocessShader(buffer, len, defines, include,
608                                 shader, error_messages);
609
610 }
611
612 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl;
613
614 typedef struct ID3DXConstantTableImpl {
615     const ID3DXConstantTableVtbl *lpVtbl;
616     LONG ref;
617     LPVOID ctab;
618     DWORD size;
619     D3DXCONSTANTTABLE_DESC desc;
620 } ID3DXConstantTableImpl;
621
622 /*** IUnknown methods ***/
623 static HRESULT WINAPI ID3DXConstantTableImpl_QueryInterface(ID3DXConstantTable* iface, REFIID riid, void** ppvObject)
624 {
625     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
626
627     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
628
629     if (IsEqualGUID(riid, &IID_IUnknown) ||
630         IsEqualGUID(riid, &IID_ID3DXBuffer) ||
631         IsEqualGUID(riid, &IID_ID3DXConstantTable))
632     {
633         ID3DXConstantTable_AddRef(iface);
634         *ppvObject = This;
635         return S_OK;
636     }
637
638     WARN("Interface %s not found.\n", debugstr_guid(riid));
639
640     return E_NOINTERFACE;
641 }
642
643 static ULONG WINAPI ID3DXConstantTableImpl_AddRef(ID3DXConstantTable* iface)
644 {
645     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
646
647     TRACE("(%p)->(): AddRef from %d\n", This, This->ref);
648
649     return InterlockedIncrement(&This->ref);
650 }
651
652 static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable* iface)
653 {
654     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
655     ULONG ref = InterlockedDecrement(&This->ref);
656
657     TRACE("(%p)->(): Release from %d\n", This, ref + 1);
658
659     if (!ref)
660     {
661         HeapFree(GetProcessHeap(), 0, This->ctab);
662         HeapFree(GetProcessHeap(), 0, This);
663     }
664
665     return ref;
666 }
667
668 /*** ID3DXBuffer methods ***/
669 static LPVOID WINAPI ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable* iface)
670 {
671     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
672
673     TRACE("(%p)->()\n", This);
674
675     return This->ctab;
676 }
677
678 static DWORD WINAPI ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable* iface)
679 {
680     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
681
682     TRACE("(%p)->()\n", This);
683
684     return This->size;
685 }
686
687 /*** ID3DXConstantTable methods ***/
688 static HRESULT WINAPI ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable* iface, D3DXCONSTANTTABLE_DESC *desc)
689 {
690     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
691
692     TRACE("(%p)->(%p)\n", This, desc);
693
694     if (!desc)
695         return D3DERR_INVALIDCALL;
696
697     memcpy(desc, &This->desc, sizeof(This->desc));
698
699     return D3D_OK;
700 }
701
702 static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable* iface, D3DXHANDLE constant,
703                                                              D3DXCONSTANT_DESC *desc, UINT *count)
704 {
705     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
706
707     FIXME("(%p)->(%p, %p, %p): stub\n", This, constant, desc, count);
708
709     return E_NOTIMPL;
710 }
711
712 static UINT WINAPI ID3DXConstantTableImpl_GetSamplerIndex(LPD3DXCONSTANTTABLE iface, D3DXHANDLE constant)
713 {
714     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
715
716     FIXME("(%p)->(%p): stub\n", This, constant);
717
718     return (UINT)-1;
719 }
720
721 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable* iface, D3DXHANDLE constant, UINT index)
722 {
723     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
724
725     FIXME("(%p)->(%p, %d): stub\n", This, constant, index);
726
727     return NULL;
728 }
729
730 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable* iface, D3DXHANDLE constant, LPCSTR name)
731 {
732     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
733
734     FIXME("(%p)->(%p, %s): stub\n", This, constant, name);
735
736     return NULL;
737 }
738
739 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable* iface, D3DXHANDLE constant, UINT index)
740 {
741     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
742
743     FIXME("(%p)->(%p, %d): stub\n", This, constant, index);
744
745     return NULL;
746 }
747
748 static HRESULT WINAPI ID3DXConstantTableImpl_SetDefaults(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device)
749 {
750     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
751
752     FIXME("(%p)->(%p): stub\n", This, device);
753
754     return E_NOTIMPL;
755 }
756
757 static HRESULT WINAPI ID3DXConstantTableImpl_SetValue(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
758                                                       D3DXHANDLE constant, LPCVOID data, UINT bytes)
759 {
760     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
761
762     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, data, bytes);
763
764     return E_NOTIMPL;
765 }
766
767 static HRESULT WINAPI ID3DXConstantTableImpl_SetBool(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
768                                                      D3DXHANDLE constant, BOOL b)
769 {
770     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
771
772     FIXME("(%p)->(%p, %p, %d): stub\n", This, device, constant, b);
773
774     return E_NOTIMPL;
775 }
776
777 static HRESULT WINAPI ID3DXConstantTableImpl_SetBoolArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
778                                                           D3DXHANDLE constant, CONST BOOL* b, UINT count)
779 {
780     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
781
782     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, b, count);
783
784     return E_NOTIMPL;
785 }
786
787 static HRESULT WINAPI ID3DXConstantTableImpl_SetInt(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device, D3DXHANDLE constant, INT n)
788 {
789     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
790
791     FIXME("(%p)->(%p, %p, %d): stub\n", This, device, constant, n);
792
793     return E_NOTIMPL;
794 }
795
796 static HRESULT WINAPI ID3DXConstantTableImpl_SetIntArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
797                                                          D3DXHANDLE constant, CONST INT* n, UINT count)
798 {
799     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
800
801     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, n, count);
802
803     return E_NOTIMPL;
804 }
805
806 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloat(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
807                                                       D3DXHANDLE constant, FLOAT f)
808 {
809     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
810
811     FIXME("(%p)->(%p, %p, %f): stub\n", This, device, constant, f);
812
813     return E_NOTIMPL;
814 }
815
816 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloatArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
817                                                            D3DXHANDLE constant, CONST FLOAT* f, UINT count)
818 {
819     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
820
821     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, f, count);
822
823     return E_NOTIMPL;
824 }
825
826 static HRESULT WINAPI ID3DXConstantTableImpl_SetVector(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
827                                                        D3DXHANDLE constant, CONST D3DXVECTOR4* vector)
828 {
829     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
830
831     FIXME("(%p)->(%p, %p, %p): stub\n", This, device, constant, vector);
832
833     return E_NOTIMPL;
834 }
835
836 static HRESULT WINAPI ID3DXConstantTableImpl_SetVectorArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
837                                                             D3DXHANDLE constant, CONST D3DXVECTOR4* vector, UINT count)
838 {
839     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
840
841     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, vector, count);
842
843     return E_NOTIMPL;
844 }
845
846 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrix(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
847                                                        D3DXHANDLE constant, CONST D3DXMATRIX* matrix)
848 {
849     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
850
851     FIXME("(%p)->(%p, %p, %p): stub\n", This, device, constant, matrix);
852
853     return E_NOTIMPL;
854 }
855
856 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
857                                                             D3DXHANDLE constant, CONST D3DXMATRIX* matrix, UINT count)
858 {
859     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
860
861     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
862
863     return E_NOTIMPL;
864 }
865
866 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixPointerArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
867                                                                    D3DXHANDLE constant, CONST D3DXMATRIX** matrix, UINT count)
868 {
869     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
870
871     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
872
873     return E_NOTIMPL;
874 }
875
876 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTranspose(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
877                                                                 D3DXHANDLE constant, CONST D3DXMATRIX* matrix)
878 {
879     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
880
881     FIXME("(%p)->(%p, %p, %p): stub\n", This, device, constant, matrix);
882
883     return E_NOTIMPL;
884 }
885
886 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposeArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
887                                                                      D3DXHANDLE constant, CONST D3DXMATRIX* matrix, UINT count)
888 {
889     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
890
891     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
892
893     return E_NOTIMPL;
894 }
895
896 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposePointerArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
897                                                                             D3DXHANDLE constant, CONST D3DXMATRIX** matrix, UINT count)
898 {
899     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
900
901     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
902
903     return E_NOTIMPL;
904 }
905
906 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl =
907 {
908     /*** IUnknown methods ***/
909     ID3DXConstantTableImpl_QueryInterface,
910     ID3DXConstantTableImpl_AddRef,
911     ID3DXConstantTableImpl_Release,
912     /*** ID3DXBuffer methods ***/
913     ID3DXConstantTableImpl_GetBufferPointer,
914     ID3DXConstantTableImpl_GetBufferSize,
915     /*** ID3DXConstantTable methods ***/
916     ID3DXConstantTableImpl_GetDesc,
917     ID3DXConstantTableImpl_GetConstantDesc,
918     ID3DXConstantTableImpl_GetSamplerIndex,
919     ID3DXConstantTableImpl_GetConstant,
920     ID3DXConstantTableImpl_GetConstantByName,
921     ID3DXConstantTableImpl_GetConstantElement,
922     ID3DXConstantTableImpl_SetDefaults,
923     ID3DXConstantTableImpl_SetValue,
924     ID3DXConstantTableImpl_SetBool,
925     ID3DXConstantTableImpl_SetBoolArray,
926     ID3DXConstantTableImpl_SetInt,
927     ID3DXConstantTableImpl_SetIntArray,
928     ID3DXConstantTableImpl_SetFloat,
929     ID3DXConstantTableImpl_SetFloatArray,
930     ID3DXConstantTableImpl_SetVector,
931     ID3DXConstantTableImpl_SetVectorArray,
932     ID3DXConstantTableImpl_SetMatrix,
933     ID3DXConstantTableImpl_SetMatrixArray,
934     ID3DXConstantTableImpl_SetMatrixPointerArray,
935     ID3DXConstantTableImpl_SetMatrixTranspose,
936     ID3DXConstantTableImpl_SetMatrixTransposeArray,
937     ID3DXConstantTableImpl_SetMatrixTransposePointerArray
938 };
939
940 HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code,
941                                             DWORD flags,
942                                             LPD3DXCONSTANTTABLE* constant_table)
943 {
944     ID3DXConstantTableImpl* object = NULL;
945     HRESULT hr;
946     LPCVOID data;
947     UINT size;
948     const D3DXSHADER_CONSTANTTABLE* ctab_header;
949
950     FIXME("(%p, %x, %p): semi-stub\n", byte_code, flags, constant_table);
951
952     if (!byte_code || !constant_table)
953         return D3DERR_INVALIDCALL;
954
955     hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), &data, &size);
956     if (hr != D3D_OK)
957         return D3DXERR_INVALIDDATA;
958
959     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ID3DXConstantTableImpl));
960     if (!object)
961     {
962         ERR("Out of memory\n");
963         return E_OUTOFMEMORY;
964     }
965
966     object->lpVtbl = &ID3DXConstantTable_Vtbl;
967     object->ref = 1;
968
969     if (size < sizeof(D3DXSHADER_CONSTANTTABLE))
970         goto error;
971
972     object->ctab = HeapAlloc(GetProcessHeap(), 0, size);
973     if (!object->ctab)
974     {
975         HeapFree(GetProcessHeap(), 0, object);
976         ERR("Out of memory\n");
977         return E_OUTOFMEMORY;
978     }
979     object->size = size;
980     memcpy(object->ctab, data, object->size);
981
982     ctab_header = (const D3DXSHADER_CONSTANTTABLE*)data;
983     if (ctab_header->Size != sizeof(D3DXSHADER_CONSTANTTABLE))
984         goto error;
985     object->desc.Creator = ctab_header->Creator ? (LPCSTR)object->ctab + ctab_header->Creator : NULL;
986     object->desc.Version = ctab_header->Version;
987     object->desc.Constants = ctab_header->Constants;
988
989     *constant_table = (LPD3DXCONSTANTTABLE)object;
990
991     return D3D_OK;
992
993 error:
994
995     HeapFree(GetProcessHeap(), 0, object->ctab);
996     HeapFree(GetProcessHeap(), 0, object);
997
998     return D3DXERR_INVALIDDATA;
999 }
1000
1001 HRESULT WINAPI D3DXGetShaderConstantTable(CONST DWORD* byte_code,
1002                                           LPD3DXCONSTANTTABLE* constant_table)
1003 {
1004     TRACE("(%p, %p): Forwarded to D3DXGetShaderConstantTableEx\n", byte_code, constant_table);
1005
1006     return D3DXGetShaderConstantTableEx(byte_code, 0, constant_table);
1007 }