d3dx9_36: Add a trailing '\n' to a TRACE().
[wine] / dlls / d3dx9_36 / shader.c
1 /*
2  * Copyright 2008 Luis Busquets
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20 #include "wine/port.h"
21 #include "wine/debug.h"
22 #include "wine/unicode.h"
23 #include "windef.h"
24 #include "wingdi.h"
25 #include "d3dx9.h"
26 #include "d3dx9shader.h"
27 #include "d3dx9_36_private.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
30
31 LPCSTR WINAPI D3DXGetPixelShaderProfile(LPDIRECT3DDEVICE9 device)
32 {
33     D3DCAPS9 caps;
34
35     TRACE("device %p\n", device);
36
37     if (!device) return NULL;
38
39     IDirect3DDevice9_GetDeviceCaps(device,&caps);
40
41     switch (caps.PixelShaderVersion)
42     {
43     case D3DPS_VERSION(1, 1):
44         return "ps_1_1";
45
46     case D3DPS_VERSION(1, 2):
47         return "ps_1_2";
48
49     case D3DPS_VERSION(1, 3):
50         return "ps_1_3";
51
52     case D3DPS_VERSION(1, 4):
53         return "ps_1_4";
54
55     case D3DPS_VERSION(2, 0):
56         if ((caps.PS20Caps.NumTemps>=22)                          &&
57             (caps.PS20Caps.Caps&D3DPS20CAPS_ARBITRARYSWIZZLE)     &&
58             (caps.PS20Caps.Caps&D3DPS20CAPS_GRADIENTINSTRUCTIONS) &&
59             (caps.PS20Caps.Caps&D3DPS20CAPS_PREDICATION)          &&
60             (caps.PS20Caps.Caps&D3DPS20CAPS_NODEPENDENTREADLIMIT) &&
61             (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
62         {
63             return "ps_2_a";
64         }
65         if ((caps.PS20Caps.NumTemps>=32)                          &&
66             (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
67         {
68             return "ps_2_b";
69         }
70         return "ps_2_0";
71
72     case D3DPS_VERSION(3, 0):
73         return "ps_3_0";
74     }
75
76     return NULL;
77 }
78
79 UINT WINAPI D3DXGetShaderSize(const DWORD *byte_code)
80 {
81     const DWORD *ptr = byte_code;
82
83     TRACE("byte_code %p\n", byte_code);
84
85     if (!ptr) return 0;
86
87     /* Look for the END token, skipping the VERSION token */
88     while (*++ptr != D3DSIO_END)
89     {
90         /* Skip comments */
91         if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
92         {
93             ptr += ((*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT);
94         }
95     }
96     ++ptr;
97
98     /* Return the shader size in bytes */
99     return (ptr - byte_code) * sizeof(*ptr);
100 }
101
102 DWORD WINAPI D3DXGetShaderVersion(const DWORD *byte_code)
103 {
104     TRACE("byte_code %p\n", byte_code);
105
106     return byte_code ? *byte_code : 0;
107 }
108
109 LPCSTR WINAPI D3DXGetVertexShaderProfile(LPDIRECT3DDEVICE9 device)
110 {
111     D3DCAPS9 caps;
112
113     TRACE("device %p\n", device);
114
115     if (!device) return NULL;
116
117     IDirect3DDevice9_GetDeviceCaps(device,&caps);
118
119     switch (caps.VertexShaderVersion)
120     {
121     case D3DVS_VERSION(1, 1):
122         return "vs_1_1";
123     case D3DVS_VERSION(2, 0):
124         if ((caps.VS20Caps.NumTemps>=13) &&
125             (caps.VS20Caps.DynamicFlowControlDepth==24) &&
126             (caps.VS20Caps.Caps&D3DPS20CAPS_PREDICATION))
127         {
128             return "vs_2_a";
129         }
130         return "vs_2_0";
131     case D3DVS_VERSION(3, 0):
132         return "vs_3_0";
133     }
134
135     return NULL;
136 }
137
138 HRESULT WINAPI D3DXFindShaderComment(CONST DWORD* byte_code, DWORD fourcc, LPCVOID* data, UINT* size)
139 {
140     CONST DWORD *ptr = byte_code;
141
142     TRACE("(%p, %x, %p, %p)\n", byte_code, fourcc, data, size);
143
144     if (!byte_code)
145         return D3DERR_INVALIDCALL;
146
147     while (*++ptr != D3DSIO_END)
148     {
149         /* Check if it is a comment */
150         if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
151         {
152             DWORD comment_size = (*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
153
154             /* Check if this is the comment we are looking for */
155             if (*(ptr + 1) == fourcc)
156             {
157                 UINT ctab_size = (comment_size - 1) * sizeof(DWORD);
158                 LPCVOID ctab_data = ptr + 2;
159                 if (size)
160                     *size = ctab_size;
161                 if (data)
162                     *data = ctab_data;
163                 TRACE("Returning comment data at %p with size %d\n", ctab_data, ctab_size);
164                 return D3D_OK;
165             }
166             ptr += comment_size;
167         }
168     }
169
170     return S_FALSE;
171 }
172
173 HRESULT WINAPI D3DXAssembleShader(LPCSTR data,
174                                   UINT data_len,
175                                   CONST D3DXMACRO* defines,
176                                   LPD3DXINCLUDE include,
177                                   DWORD flags,
178                                   LPD3DXBUFFER* shader,
179                                   LPD3DXBUFFER* error_messages)
180 {
181     FIXME("(%p, %d, %p, %p, %x, %p, %p): stub\n", data, data_len, defines, include, flags, shader, error_messages);
182     return D3DERR_INVALIDCALL;
183 }
184
185 HRESULT WINAPI D3DXAssembleShaderFromFileA(LPCSTR filename,
186                                            CONST D3DXMACRO* defines,
187                                            LPD3DXINCLUDE include,
188                                            DWORD flags,
189                                            LPD3DXBUFFER* shader,
190                                            LPD3DXBUFFER* error_messages)
191 {
192     LPWSTR filename_w = NULL;
193     DWORD len;
194     HRESULT ret;
195
196     if (!filename) return D3DXERR_INVALIDDATA;
197
198     len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
199     filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
200     if (!filename_w) return E_OUTOFMEMORY;
201     MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
202
203     ret = D3DXAssembleShaderFromFileW(filename_w, defines, include, flags, shader, error_messages);
204
205     HeapFree(GetProcessHeap(), 0, filename_w);
206     return ret;
207 }
208
209 HRESULT WINAPI D3DXAssembleShaderFromFileW(LPCWSTR filename,
210                                            CONST D3DXMACRO* defines,
211                                            LPD3DXINCLUDE include,
212                                            DWORD flags,
213                                            LPD3DXBUFFER* shader,
214                                            LPD3DXBUFFER* error_messages)
215 {
216     FIXME("(%s, %p, %p, %x, %p, %p): stub\n", debugstr_w(filename), defines, include, flags, shader, error_messages);
217     return D3DERR_INVALIDCALL;
218 }
219
220 HRESULT WINAPI D3DXAssembleShaderFromResourceA(HMODULE module,
221                                                LPCSTR resource,
222                                                CONST D3DXMACRO* defines,
223                                                LPD3DXINCLUDE include,
224                                                DWORD flags,
225                                                LPD3DXBUFFER* shader,
226                                                LPD3DXBUFFER* error_messages)
227 {
228     HRSRC res;
229     LPCSTR buffer;
230     DWORD len;
231
232     if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
233         return D3DXERR_INVALIDDATA;
234     if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
235         return D3DXERR_INVALIDDATA;
236     return D3DXAssembleShader(buffer, len, defines, include, flags,
237                               shader, error_messages);
238 }
239
240 HRESULT WINAPI D3DXAssembleShaderFromResourceW(HMODULE module,
241                                                LPCWSTR resource,
242                                                CONST D3DXMACRO* defines,
243                                                LPD3DXINCLUDE include,
244                                                DWORD flags,
245                                                LPD3DXBUFFER* shader,
246                                                LPD3DXBUFFER* error_messages)
247 {
248     HRSRC res;
249     LPCSTR buffer;
250     DWORD len;
251
252     if (!(res = FindResourceW(module, resource, (LPCWSTR)RT_RCDATA)))
253         return D3DXERR_INVALIDDATA;
254     if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
255         return D3DXERR_INVALIDDATA;
256     return D3DXAssembleShader(buffer, len, defines, include, flags,
257                               shader, error_messages);
258 }
259
260 HRESULT WINAPI D3DXCompileShader(LPCSTR pSrcData,
261                                  UINT srcDataLen,
262                                  CONST D3DXMACRO* pDefines,
263                                  LPD3DXINCLUDE pInclude,
264                                  LPCSTR pFunctionName,
265                                  LPCSTR pProfile,
266                                  DWORD Flags,
267                                  LPD3DXBUFFER* ppShader,
268                                  LPD3DXBUFFER* ppErrorMsgs,
269                                  LPD3DXCONSTANTTABLE * ppConstantTable)
270 {
271     FIXME("(%p, %d, %p, %p, %p, %p, %d, %p, %p, %p): stub\n",
272           pSrcData, srcDataLen, pDefines, pInclude, pFunctionName,
273           pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
274     return D3DERR_INVALIDCALL;
275 }
276
277 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl;
278
279 typedef struct ID3DXConstantTableImpl {
280     const ID3DXConstantTableVtbl *lpVtbl;
281     LONG ref;
282     LPVOID ctab;
283     DWORD size;
284     D3DXCONSTANTTABLE_DESC desc;
285 } ID3DXConstantTableImpl;
286
287 /*** IUnknown methods ***/
288 static HRESULT WINAPI ID3DXConstantTableImpl_QueryInterface(ID3DXConstantTable* iface, REFIID riid, void** ppvObject)
289 {
290     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
291
292     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
293
294     if (IsEqualGUID(riid, &IID_IUnknown) ||
295         IsEqualGUID(riid, &IID_ID3DXBuffer) ||
296         IsEqualGUID(riid, &IID_ID3DXConstantTable))
297     {
298         ID3DXConstantTable_AddRef(iface);
299         *ppvObject = This;
300         return S_OK;
301     }
302
303     WARN("Interface %s not found.\n", debugstr_guid(riid));
304
305     return E_NOINTERFACE;
306 }
307
308 static ULONG WINAPI ID3DXConstantTableImpl_AddRef(ID3DXConstantTable* iface)
309 {
310     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
311
312     TRACE("(%p)->(): AddRef from %d\n", This, This->ref);
313
314     return InterlockedIncrement(&This->ref);
315 }
316
317 static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable* iface)
318 {
319     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
320     ULONG ref = InterlockedDecrement(&This->ref);
321
322     TRACE("(%p)->(): Release from %d\n", This, ref + 1);
323
324     if (!ref)
325     {
326         HeapFree(GetProcessHeap(), 0, This->ctab);
327         HeapFree(GetProcessHeap(), 0, This);
328     }
329
330     return ref;
331 }
332
333 /*** ID3DXBuffer methods ***/
334 static LPVOID WINAPI ID3DXConstantTableImpl_GetBufferPointer(ID3DXConstantTable* iface)
335 {
336     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
337
338     TRACE("(%p)->()\n", This);
339
340     return This->ctab;
341 }
342
343 static DWORD WINAPI ID3DXConstantTableImpl_GetBufferSize(ID3DXConstantTable* iface)
344 {
345     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
346
347     TRACE("(%p)->()\n", This);
348
349     return This->size;
350 }
351
352 /*** ID3DXConstantTable methods ***/
353 static HRESULT WINAPI ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable* iface, D3DXCONSTANTTABLE_DESC *desc)
354 {
355     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
356
357     TRACE("(%p)->(%p)\n", This, desc);
358
359     if (!desc)
360         return D3DERR_INVALIDCALL;
361
362     memcpy(desc, &This->desc, sizeof(This->desc));
363
364     return D3D_OK;
365 }
366
367 static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable* iface, D3DXHANDLE constant,
368                                                              D3DXCONSTANT_DESC *desc, UINT *count)
369 {
370     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
371
372     FIXME("(%p)->(%p, %p, %p): stub\n", This, constant, desc, count);
373
374     return E_NOTIMPL;
375 }
376
377 static UINT WINAPI ID3DXConstantTableImpl_GetSamplerIndex(LPD3DXCONSTANTTABLE iface, D3DXHANDLE constant)
378 {
379     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
380
381     FIXME("(%p)->(%p): stub\n", This, constant);
382
383     return (UINT)-1;
384 }
385
386 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable* iface, D3DXHANDLE constant, UINT index)
387 {
388     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
389
390     FIXME("(%p)->(%p, %d): stub\n", This, constant, index);
391
392     return NULL;
393 }
394
395 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable* iface, D3DXHANDLE constant, LPCSTR name)
396 {
397     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
398
399     FIXME("(%p)->(%p, %s): stub\n", This, constant, name);
400
401     return NULL;
402 }
403
404 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable* iface, D3DXHANDLE constant, UINT index)
405 {
406     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
407
408     FIXME("(%p)->(%p, %d): stub\n", This, constant, index);
409
410     return NULL;
411 }
412
413 static HRESULT WINAPI ID3DXConstantTableImpl_SetDefaults(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device)
414 {
415     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
416
417     FIXME("(%p)->(%p): stub\n", This, device);
418
419     return E_NOTIMPL;
420 }
421
422 static HRESULT WINAPI ID3DXConstantTableImpl_SetValue(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
423                                                       D3DXHANDLE constant, LPCVOID data, UINT bytes)
424 {
425     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
426
427     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, data, bytes);
428
429     return E_NOTIMPL;
430 }
431
432 static HRESULT WINAPI ID3DXConstantTableImpl_SetBool(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
433                                                      D3DXHANDLE constant, BOOL b)
434 {
435     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
436
437     FIXME("(%p)->(%p, %p, %d): stub\n", This, device, constant, b);
438
439     return E_NOTIMPL;
440 }
441
442 static HRESULT WINAPI ID3DXConstantTableImpl_SetBoolArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
443                                                           D3DXHANDLE constant, CONST BOOL* b, UINT count)
444 {
445     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
446
447     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, b, count);
448
449     return E_NOTIMPL;
450 }
451
452 static HRESULT WINAPI ID3DXConstantTableImpl_SetInt(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device, D3DXHANDLE constant, INT n)
453 {
454     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
455
456     FIXME("(%p)->(%p, %p, %d): stub\n", This, device, constant, n);
457
458     return E_NOTIMPL;
459 }
460
461 static HRESULT WINAPI ID3DXConstantTableImpl_SetIntArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
462                                                          D3DXHANDLE constant, CONST INT* n, UINT count)
463 {
464     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
465
466     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, n, count);
467
468     return E_NOTIMPL;
469 }
470
471 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloat(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
472                                                       D3DXHANDLE constant, FLOAT f)
473 {
474     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
475
476     FIXME("(%p)->(%p, %p, %f): stub\n", This, device, constant, f);
477
478     return E_NOTIMPL;
479 }
480
481 static HRESULT WINAPI ID3DXConstantTableImpl_SetFloatArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
482                                                            D3DXHANDLE constant, CONST FLOAT* f, UINT count)
483 {
484     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
485
486     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, f, count);
487
488     return E_NOTIMPL;
489 }
490
491 static HRESULT WINAPI ID3DXConstantTableImpl_SetVector(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
492                                                        D3DXHANDLE constant, CONST D3DXVECTOR4* vector)
493 {
494     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
495
496     FIXME("(%p)->(%p, %p, %p): stub\n", This, device, constant, vector);
497
498     return E_NOTIMPL;
499 }
500
501 static HRESULT WINAPI ID3DXConstantTableImpl_SetVectorArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
502                                                             D3DXHANDLE constant, CONST D3DXVECTOR4* vector, UINT count)
503 {
504     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
505
506     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, vector, count);
507
508     return E_NOTIMPL;
509 }
510
511 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrix(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
512                                                        D3DXHANDLE constant, CONST D3DXMATRIX* matrix)
513 {
514     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
515
516     FIXME("(%p)->(%p, %p, %p): stub\n", This, device, constant, matrix);
517
518     return E_NOTIMPL;
519 }
520
521 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
522                                                             D3DXHANDLE constant, CONST D3DXMATRIX* matrix, UINT count)
523 {
524     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
525
526     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
527
528     return E_NOTIMPL;
529 }
530
531 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixPointerArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
532                                                                    D3DXHANDLE constant, CONST D3DXMATRIX** matrix, UINT count)
533 {
534     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
535
536     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
537
538     return E_NOTIMPL;
539 }
540
541 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTranspose(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
542                                                                 D3DXHANDLE constant, CONST D3DXMATRIX* matrix)
543 {
544     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
545
546     FIXME("(%p)->(%p, %p, %p): stub\n", This, device, constant, matrix);
547
548     return E_NOTIMPL;
549 }
550
551 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposeArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
552                                                                      D3DXHANDLE constant, CONST D3DXMATRIX* matrix, UINT count)
553 {
554     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
555
556     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
557
558     return E_NOTIMPL;
559 }
560
561 static HRESULT WINAPI ID3DXConstantTableImpl_SetMatrixTransposePointerArray(ID3DXConstantTable* iface, LPDIRECT3DDEVICE9 device,
562                                                                             D3DXHANDLE constant, CONST D3DXMATRIX** matrix, UINT count)
563 {
564     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
565
566     FIXME("(%p)->(%p, %p, %p, %d): stub\n", This, device, constant, matrix, count);
567
568     return E_NOTIMPL;
569 }
570
571 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl =
572 {
573     /*** IUnknown methods ***/
574     ID3DXConstantTableImpl_QueryInterface,
575     ID3DXConstantTableImpl_AddRef,
576     ID3DXConstantTableImpl_Release,
577     /*** ID3DXBuffer methods ***/
578     ID3DXConstantTableImpl_GetBufferPointer,
579     ID3DXConstantTableImpl_GetBufferSize,
580     /*** ID3DXConstantTable methods ***/
581     ID3DXConstantTableImpl_GetDesc,
582     ID3DXConstantTableImpl_GetConstantDesc,
583     ID3DXConstantTableImpl_GetSamplerIndex,
584     ID3DXConstantTableImpl_GetConstant,
585     ID3DXConstantTableImpl_GetConstantByName,
586     ID3DXConstantTableImpl_GetConstantElement,
587     ID3DXConstantTableImpl_SetDefaults,
588     ID3DXConstantTableImpl_SetValue,
589     ID3DXConstantTableImpl_SetBool,
590     ID3DXConstantTableImpl_SetBoolArray,
591     ID3DXConstantTableImpl_SetInt,
592     ID3DXConstantTableImpl_SetIntArray,
593     ID3DXConstantTableImpl_SetFloat,
594     ID3DXConstantTableImpl_SetFloatArray,
595     ID3DXConstantTableImpl_SetVector,
596     ID3DXConstantTableImpl_SetVectorArray,
597     ID3DXConstantTableImpl_SetMatrix,
598     ID3DXConstantTableImpl_SetMatrixArray,
599     ID3DXConstantTableImpl_SetMatrixPointerArray,
600     ID3DXConstantTableImpl_SetMatrixTranspose,
601     ID3DXConstantTableImpl_SetMatrixTransposeArray,
602     ID3DXConstantTableImpl_SetMatrixTransposePointerArray
603 };
604
605 HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code,
606                                             DWORD flags,
607                                             LPD3DXCONSTANTTABLE* constant_table)
608 {
609     ID3DXConstantTableImpl* object = NULL;
610     HRESULT hr;
611     LPCVOID data;
612     UINT size;
613     D3DXSHADER_CONSTANTTABLE* ctab_header;
614
615     FIXME("(%p, %x, %p): semi-stub\n", byte_code, flags, constant_table);
616
617     if (!byte_code || !constant_table)
618         return D3DERR_INVALIDCALL;
619
620     hr = D3DXFindShaderComment(byte_code, MAKEFOURCC('C','T','A','B'), &data, &size);
621     if (hr != D3D_OK)
622         return D3DXERR_INVALIDDATA;
623
624     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ID3DXConstantTableImpl));
625     if (!object)
626     {
627         ERR("Out of memory\n");
628         return E_OUTOFMEMORY;
629     }
630
631     object->lpVtbl = &ID3DXConstantTable_Vtbl;
632     object->ref = 1;
633
634     if (size < sizeof(D3DXSHADER_CONSTANTTABLE))
635         goto error;
636
637     object->ctab = HeapAlloc(GetProcessHeap(), 0, size);
638     if (!object->ctab)
639     {
640         HeapFree(GetProcessHeap(), 0, object);
641         ERR("Out of memory\n");
642         return E_OUTOFMEMORY;
643     }
644     object->size = size;
645     memcpy(object->ctab, data, object->size);
646
647     ctab_header = (D3DXSHADER_CONSTANTTABLE*)data;
648     if (ctab_header->Size != sizeof(D3DXSHADER_CONSTANTTABLE))
649         goto error;
650     object->desc.Creator = ctab_header->Creator ? (LPCSTR)object->ctab + ctab_header->Creator : NULL;
651     object->desc.Version = ctab_header->Version;
652     object->desc.Constants = ctab_header->Constants;
653
654     *constant_table = (LPD3DXCONSTANTTABLE)object;
655
656     return D3D_OK;
657
658 error:
659
660     HeapFree(GetProcessHeap(), 0, object->ctab);
661     HeapFree(GetProcessHeap(), 0, object);
662
663     return D3DXERR_INVALIDDATA;
664 }
665
666 HRESULT WINAPI D3DXGetShaderConstantTable(CONST DWORD* byte_code,
667                                           LPD3DXCONSTANTTABLE* constant_table)
668 {
669     TRACE("(%p, %p): Forwarded to D3DXGetShaderConstantTableEx\n", byte_code, constant_table);
670
671     return D3DXGetShaderConstantTableEx(byte_code, 0, constant_table);
672 }