d3dx9: Fix D3DXCompileShaderFromFileW.
[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, (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 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl;
509
510 typedef struct ID3DXConstantTableImpl {
511     const ID3DXConstantTableVtbl *lpVtbl;
512     LONG ref;
513     LPVOID ctab;
514     DWORD size;
515     D3DXCONSTANTTABLE_DESC desc;
516 } ID3DXConstantTableImpl;
517
518 /*** IUnknown methods ***/
519 static HRESULT WINAPI ID3DXConstantTableImpl_QueryInterface(ID3DXConstantTable* iface, REFIID riid, void** ppvObject)
520 {
521     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
522
523     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
524
525     if (IsEqualGUID(riid, &IID_IUnknown) ||
526         IsEqualGUID(riid, &IID_ID3DXBuffer) ||
527         IsEqualGUID(riid, &IID_ID3DXConstantTable))
528     {
529         ID3DXConstantTable_AddRef(iface);
530         *ppvObject = This;
531         return S_OK;
532     }
533
534     WARN("Interface %s not found.\n", debugstr_guid(riid));
535
536     return E_NOINTERFACE;
537 }
538
539 static ULONG WINAPI ID3DXConstantTableImpl_AddRef(ID3DXConstantTable* iface)
540 {
541     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
542
543     TRACE("(%p)->(): AddRef from %d\n", This, This->ref);
544
545     return InterlockedIncrement(&This->ref);
546 }
547
548 static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable* iface)
549 {
550     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
551     ULONG ref = InterlockedDecrement(&This->ref);
552
553     TRACE("(%p)->(): Release from %d\n", This, ref + 1);
554
555     if (!ref)
556     {
557         HeapFree(GetProcessHeap(), 0, This->ctab);
558         HeapFree(GetProcessHeap(), 0, This);
559     }
560
561     return ref;
562 }
563
564 /*** ID3DXBuffer methods ***/
565 static LPVOID WINAPI ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable* iface)
566 {
567     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
568
569     TRACE("(%p)->()\n", This);
570
571     return This->ctab;
572 }
573
574 static DWORD WINAPI ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable* iface)
575 {
576     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
577
578     TRACE("(%p)->()\n", This);
579
580     return This->size;
581 }
582
583 /*** ID3DXConstantTable methods ***/
584 static HRESULT WINAPI ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable* iface, D3DXCONSTANTTABLE_DESC *desc)
585 {
586     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
587
588     TRACE("(%p)->(%p)\n", This, desc);
589
590     if (!desc)
591         return D3DERR_INVALIDCALL;
592
593     memcpy(desc, &This->desc, sizeof(This->desc));
594
595     return D3D_OK;
596 }
597
598 static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable* iface, D3DXHANDLE constant,
599                                                              D3DXCONSTANT_DESC *desc, UINT *count)
600 {
601     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
602
603     FIXME("(%p)->(%p, %p, %p): stub\n", This, constant, desc, count);
604
605     return E_NOTIMPL;
606 }
607
608 static UINT WINAPI ID3DXConstantTableImpl_GetSamplerIndex(LPD3DXCONSTANTTABLE iface, D3DXHANDLE constant)
609 {
610     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
611
612     FIXME("(%p)->(%p): stub\n", This, constant);
613
614     return (UINT)-1;
615 }
616
617 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable* iface, D3DXHANDLE constant, UINT index)
618 {
619     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
620
621     FIXME("(%p)->(%p, %d): stub\n", This, constant, index);
622
623     return NULL;
624 }
625
626 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable* iface, D3DXHANDLE constant, LPCSTR name)
627 {
628     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
629
630     FIXME("(%p)->(%p, %s): stub\n", This, constant, name);
631
632     return NULL;
633 }
634
635 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable* iface, D3DXHANDLE constant, UINT index)
636 {
637     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
638
639     FIXME("(%p)->(%p, %d): stub\n", This, constant, index);
640
641     return NULL;
642 }
643
644 static HRESULT WINAPI ID3DXConstantTableImpl_SetDefaults(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device)
645 {
646     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
647
648     FIXME("(%p)->(%p): stub\n", This, device);
649
650     return E_NOTIMPL;
651 }
652
653 static HRESULT WINAPI ID3DXConstantTableImpl_SetValue(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
654                                                       D3DXHANDLE constant, LPCVOID data, UINT bytes)
655 {
656     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
657
658     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, data, bytes);
659
660     return E_NOTIMPL;
661 }
662
663 static HRESULT WINAPI ID3DXConstantTableImpl_SetBool(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
664                                                      D3DXHANDLE constant, BOOL b)
665 {
666     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
667
668     FIXME("(%p)->(%p, %p, %d): stub\n", This, device, constant, b);
669
670     return E_NOTIMPL;
671 }
672
673 static HRESULT WINAPI ID3DXConstantTableImpl_SetBoolArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
674                                                           D3DXHANDLE constant, CONST BOOL* b, UINT count)
675 {
676     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
677
678     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, b, count);
679
680     return E_NOTIMPL;
681 }
682
683 static HRESULT WINAPI ID3DXConstantTableImpl_SetInt(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device, D3DXHANDLE constant, INT n)
684 {
685     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
686
687     FIXME("(%p)->(%p, %p, %d): stub\n", This, device, constant, n);
688
689     return E_NOTIMPL;
690 }
691
692 static HRESULT WINAPI ID3DXConstantTableImpl_SetIntArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
693                                                          D3DXHANDLE constant, CONST INT* n, UINT count)
694 {
695     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
696
697     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, n, count);
698
699     return E_NOTIMPL;
700 }
701
702 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloat(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
703                                                       D3DXHANDLE constant, FLOAT f)
704 {
705     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
706
707     FIXME("(%p)->(%p, %p, %f): stub\n", This, device, constant, f);
708
709     return E_NOTIMPL;
710 }
711
712 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloatArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
713                                                            D3DXHANDLE constant, CONST FLOAT* f, UINT count)
714 {
715     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
716
717     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, f, count);
718
719     return E_NOTIMPL;
720 }
721
722 static HRESULT WINAPI ID3DXConstantTableImpl_SetVector(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
723                                                        D3DXHANDLE constant, CONST D3DXVECTOR4* vector)
724 {
725     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
726
727     FIXME("(%p)->(%p, %p, %p): stub\n", This, device, constant, vector);
728
729     return E_NOTIMPL;
730 }
731
732 static HRESULT WINAPI ID3DXConstantTableImpl_SetVectorArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
733                                                             D3DXHANDLE constant, CONST D3DXVECTOR4* vector, UINT count)
734 {
735     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
736
737     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, vector, count);
738
739     return E_NOTIMPL;
740 }
741
742 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrix(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
743                                                        D3DXHANDLE constant, CONST D3DXMATRIX* matrix)
744 {
745     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
746
747     FIXME("(%p)->(%p, %p, %p): stub\n", This, device, constant, matrix);
748
749     return E_NOTIMPL;
750 }
751
752 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
753                                                             D3DXHANDLE constant, CONST D3DXMATRIX* matrix, UINT count)
754 {
755     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
756
757     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
758
759     return E_NOTIMPL;
760 }
761
762 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixPointerArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
763                                                                    D3DXHANDLE constant, CONST D3DXMATRIX** matrix, UINT count)
764 {
765     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
766
767     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
768
769     return E_NOTIMPL;
770 }
771
772 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTranspose(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
773                                                                 D3DXHANDLE constant, CONST D3DXMATRIX* matrix)
774 {
775     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
776
777     FIXME("(%p)->(%p, %p, %p): stub\n", This, device, constant, matrix);
778
779     return E_NOTIMPL;
780 }
781
782 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposeArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
783                                                                      D3DXHANDLE constant, CONST D3DXMATRIX* matrix, UINT count)
784 {
785     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
786
787     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
788
789     return E_NOTIMPL;
790 }
791
792 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposePointerArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
793                                                                             D3DXHANDLE constant, CONST D3DXMATRIX** matrix, UINT count)
794 {
795     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
796
797     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
798
799     return E_NOTIMPL;
800 }
801
802 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl =
803 {
804     /*** IUnknown methods ***/
805     ID3DXConstantTableImpl_QueryInterface,
806     ID3DXConstantTableImpl_AddRef,
807     ID3DXConstantTableImpl_Release,
808     /*** ID3DXBuffer methods ***/
809     ID3DXConstantTableImpl_GetBufferPointer,
810     ID3DXConstantTableImpl_GetBufferSize,
811     /*** ID3DXConstantTable methods ***/
812     ID3DXConstantTableImpl_GetDesc,
813     ID3DXConstantTableImpl_GetConstantDesc,
814     ID3DXConstantTableImpl_GetSamplerIndex,
815     ID3DXConstantTableImpl_GetConstant,
816     ID3DXConstantTableImpl_GetConstantByName,
817     ID3DXConstantTableImpl_GetConstantElement,
818     ID3DXConstantTableImpl_SetDefaults,
819     ID3DXConstantTableImpl_SetValue,
820     ID3DXConstantTableImpl_SetBool,
821     ID3DXConstantTableImpl_SetBoolArray,
822     ID3DXConstantTableImpl_SetInt,
823     ID3DXConstantTableImpl_SetIntArray,
824     ID3DXConstantTableImpl_SetFloat,
825     ID3DXConstantTableImpl_SetFloatArray,
826     ID3DXConstantTableImpl_SetVector,
827     ID3DXConstantTableImpl_SetVectorArray,
828     ID3DXConstantTableImpl_SetMatrix,
829     ID3DXConstantTableImpl_SetMatrixArray,
830     ID3DXConstantTableImpl_SetMatrixPointerArray,
831     ID3DXConstantTableImpl_SetMatrixTranspose,
832     ID3DXConstantTableImpl_SetMatrixTransposeArray,
833     ID3DXConstantTableImpl_SetMatrixTransposePointerArray
834 };
835
836 HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code,
837                                             DWORD flags,
838                                             LPD3DXCONSTANTTABLE* constant_table)
839 {
840     ID3DXConstantTableImpl* object = NULL;
841     HRESULT hr;
842     LPCVOID data;
843     UINT size;
844     const D3DXSHADER_CONSTANTTABLE* ctab_header;
845
846     FIXME("(%p, %x, %p): semi-stub\n", byte_code, flags, constant_table);
847
848     if (!byte_code || !constant_table)
849         return D3DERR_INVALIDCALL;
850
851     hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), &data, &size);
852     if (hr != D3D_OK)
853         return D3DXERR_INVALIDDATA;
854
855     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ID3DXConstantTableImpl));
856     if (!object)
857     {
858         ERR("Out of memory\n");
859         return E_OUTOFMEMORY;
860     }
861
862     object->lpVtbl = &ID3DXConstantTable_Vtbl;
863     object->ref = 1;
864
865     if (size < sizeof(D3DXSHADER_CONSTANTTABLE))
866         goto error;
867
868     object->ctab = HeapAlloc(GetProcessHeap(), 0, size);
869     if (!object->ctab)
870     {
871         HeapFree(GetProcessHeap(), 0, object);
872         ERR("Out of memory\n");
873         return E_OUTOFMEMORY;
874     }
875     object->size = size;
876     memcpy(object->ctab, data, object->size);
877
878     ctab_header = (const D3DXSHADER_CONSTANTTABLE*)data;
879     if (ctab_header->Size != sizeof(D3DXSHADER_CONSTANTTABLE))
880         goto error;
881     object->desc.Creator = ctab_header->Creator ? (LPCSTR)object->ctab + ctab_header->Creator : NULL;
882     object->desc.Version = ctab_header->Version;
883     object->desc.Constants = ctab_header->Constants;
884
885     *constant_table = (LPD3DXCONSTANTTABLE)object;
886
887     return D3D_OK;
888
889 error:
890
891     HeapFree(GetProcessHeap(), 0, object->ctab);
892     HeapFree(GetProcessHeap(), 0, object);
893
894     return D3DXERR_INVALIDDATA;
895 }
896
897 HRESULT WINAPI D3DXGetShaderConstantTable(CONST DWORD* byte_code,
898                                           LPD3DXCONSTANTTABLE* constant_table)
899 {
900     TRACE("(%p, %p): Forwarded to D3DXGetShaderConstantTableEx\n", byte_code, constant_table);
901
902     return D3DXGetShaderConstantTableEx(byte_code, 0, constant_table);
903 }