xref: /reactos/dll/directx/wine/d3dx9_36/effect.c (revision b2df33e5)
1 #ifdef __REACTOS__
2 #include "precomp.h"
3 #else
4 /*
5  * Copyright 2010 Christian Costa
6  * Copyright 2011 Rico Schüller
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 
23 #include "config.h"
24 #include "wine/port.h"
25 
26 #include <stdio.h>
27 #include <assert.h>
28 
29 #include "d3dx9_private.h"
30 #include "d3dcompiler.h"
31 #endif /* __REACTOS__ */
32 
33 /* Constants for special INT/FLOAT conversation */
34 #define INT_FLOAT_MULTI 255.0f
35 #define INT_FLOAT_MULTI_INVERSE (1/INT_FLOAT_MULTI)
36 
37 static const char parameter_magic_string[4] = {'@', '!', '#', '\xFF'};
38 
39 #define PARAMETER_FLAG_SHARED 1
40 
41 #define INITIAL_POOL_SIZE 16
42 
43 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
44 
45 enum STATE_CLASS
46 {
47     SC_LIGHTENABLE,
48     SC_FVF,
49     SC_LIGHT,
50     SC_MATERIAL,
51     SC_NPATCHMODE,
52     SC_PIXELSHADER,
53     SC_RENDERSTATE,
54     SC_SETSAMPLER,
55     SC_SAMPLERSTATE,
56     SC_TEXTURE,
57     SC_TEXTURESTAGE,
58     SC_TRANSFORM,
59     SC_VERTEXSHADER,
60     SC_SHADERCONST,
61     SC_UNKNOWN,
62 };
63 
64 enum MATERIAL_TYPE
65 {
66     MT_DIFFUSE,
67     MT_AMBIENT,
68     MT_SPECULAR,
69     MT_EMISSIVE,
70     MT_POWER,
71 };
72 
73 enum LIGHT_TYPE
74 {
75     LT_TYPE,
76     LT_DIFFUSE,
77     LT_SPECULAR,
78     LT_AMBIENT,
79     LT_POSITION,
80     LT_DIRECTION,
81     LT_RANGE,
82     LT_FALLOFF,
83     LT_ATTENUATION0,
84     LT_ATTENUATION1,
85     LT_ATTENUATION2,
86     LT_THETA,
87     LT_PHI,
88 };
89 
90 enum SHADER_CONSTANT_TYPE
91 {
92     SCT_VSFLOAT,
93     SCT_VSBOOL,
94     SCT_VSINT,
95     SCT_PSFLOAT,
96     SCT_PSBOOL,
97     SCT_PSINT,
98 };
99 
100 enum STATE_TYPE
101 {
102     ST_CONSTANT,
103     ST_PARAMETER,
104     ST_FXLC,
105     ST_ARRAY_SELECTOR,
106 };
107 
108 struct d3dx_object
109 {
110     UINT size;
111     void *data;
112     struct d3dx_parameter *param;
113     BOOL creation_failed;
114 };
115 
116 struct d3dx_state
117 {
118     UINT operation;
119     UINT index;
120     enum STATE_TYPE type;
121     struct d3dx_parameter parameter;
122     struct d3dx_parameter *referenced_param;
123 };
124 
125 struct d3dx_sampler
126 {
127     UINT state_count;
128     struct d3dx_state *states;
129 };
130 
131 struct d3dx_pass
132 {
133     char *name;
134     UINT state_count;
135     UINT annotation_count;
136 
137     struct d3dx_state *states;
138     struct d3dx_parameter *annotations;
139 
140     ULONG64 update_version;
141 };
142 
143 struct d3dx_technique
144 {
145     char *name;
146     UINT pass_count;
147     UINT annotation_count;
148 
149     struct d3dx_parameter *annotations;
150     struct d3dx_pass *passes;
151 
152     struct IDirect3DStateBlock9 *saved_state;
153 };
154 
155 struct d3dx9_base_effect
156 {
157     struct d3dx_effect *effect;
158 
159 
160     ULONG64 version_counter;
161 };
162 
163 struct d3dx_effect
164 {
165     ID3DXEffect ID3DXEffect_iface;
166     LONG ref;
167 
168     struct d3dx9_base_effect base_effect;
169     unsigned int parameter_count;
170     unsigned int technique_count;
171     unsigned int object_count;
172     struct d3dx_top_level_parameter *parameters;
173     struct d3dx_technique *techniques;
174     struct d3dx_object *objects;
175     DWORD flags;
176     struct wine_rb_tree param_tree;
177     char *full_name_tmp;
178     unsigned int full_name_tmp_size;
179 
180     struct ID3DXEffectStateManager *manager;
181     struct IDirect3DDevice9 *device;
182     struct d3dx_effect_pool *pool;
183     struct d3dx_technique *active_technique;
184     struct d3dx_pass *active_pass;
185     BOOL started;
186     DWORD begin_flags;
187 
188     D3DLIGHT9 current_light[8];
189     unsigned int light_updated;
190     D3DMATERIAL9 current_material;
191     BOOL material_updated;
192 };
193 
194 #define INITIAL_SHARED_DATA_SIZE 4
195 
196 struct d3dx_effect_pool
197 {
198     ID3DXEffectPool ID3DXEffectPool_iface;
199     LONG refcount;
200 
201     struct d3dx_shared_data *shared_data;
202     unsigned int size;
203 
204     ULONG64 version_counter;
205 };
206 
207 struct ID3DXEffectCompilerImpl
208 {
209     ID3DXEffectCompiler ID3DXEffectCompiler_iface;
210     LONG ref;
211 };
212 
213 static HRESULT d3dx_parse_state(struct d3dx_effect *effect, struct d3dx_state *state,
214         const char *data, const char **ptr, struct d3dx_object *objects);
215 static void free_parameter(struct d3dx_parameter *param, BOOL element, BOOL child);
216 
217 typedef BOOL (*walk_parameter_dep_func)(void *data, struct d3dx_parameter *param);
218 
219 static const struct
220 {
221     enum STATE_CLASS class;
222     UINT op;
223     const char *name;
224 }
225 state_table[] =
226 {
227     /* Render states */
228     {SC_RENDERSTATE, D3DRS_ZENABLE, "D3DRS_ZENABLE"}, /* 0x0 */
229     {SC_RENDERSTATE, D3DRS_FILLMODE, "D3DRS_FILLMODE"},
230     {SC_RENDERSTATE, D3DRS_SHADEMODE, "D3DRS_SHADEMODE"},
231     {SC_RENDERSTATE, D3DRS_ZWRITEENABLE, "D3DRS_ZWRITEENABLE"},
232     {SC_RENDERSTATE, D3DRS_ALPHATESTENABLE, "D3DRS_ALPHATESTENABLE"},
233     {SC_RENDERSTATE, D3DRS_LASTPIXEL, "D3DRS_LASTPIXEL"},
234     {SC_RENDERSTATE, D3DRS_SRCBLEND, "D3DRS_SRCBLEND"},
235     {SC_RENDERSTATE, D3DRS_DESTBLEND, "D3DRS_DESTBLEND"},
236     {SC_RENDERSTATE, D3DRS_CULLMODE, "D3DRS_CULLMODE"},
237     {SC_RENDERSTATE, D3DRS_ZFUNC, "D3DRS_ZFUNC"},
238     {SC_RENDERSTATE, D3DRS_ALPHAREF, "D3DRS_ALPHAREF"},
239     {SC_RENDERSTATE, D3DRS_ALPHAFUNC, "D3DRS_ALPHAFUNC"},
240     {SC_RENDERSTATE, D3DRS_DITHERENABLE, "D3DRS_DITHERENABLE"},
241     {SC_RENDERSTATE, D3DRS_ALPHABLENDENABLE, "D3DRS_ALPHABLENDENABLE"},
242     {SC_RENDERSTATE, D3DRS_FOGENABLE, "D3DRS_FOGENABLE"},
243     {SC_RENDERSTATE, D3DRS_SPECULARENABLE, "D3DRS_SPECULARENABLE"},
244     {SC_RENDERSTATE, D3DRS_FOGCOLOR, "D3DRS_FOGCOLOR"}, /* 0x10 */
245     {SC_RENDERSTATE, D3DRS_FOGTABLEMODE, "D3DRS_FOGTABLEMODE"},
246     {SC_RENDERSTATE, D3DRS_FOGSTART, "D3DRS_FOGSTART"},
247     {SC_RENDERSTATE, D3DRS_FOGEND, "D3DRS_FOGEND"},
248     {SC_RENDERSTATE, D3DRS_FOGDENSITY, "D3DRS_FOGDENSITY"},
249     {SC_RENDERSTATE, D3DRS_RANGEFOGENABLE, "D3DRS_RANGEFOGENABLE"},
250     {SC_RENDERSTATE, D3DRS_STENCILENABLE, "D3DRS_STENCILENABLE"},
251     {SC_RENDERSTATE, D3DRS_STENCILFAIL, "D3DRS_STENCILFAIL"},
252     {SC_RENDERSTATE, D3DRS_STENCILZFAIL, "D3DRS_STENCILZFAIL"},
253     {SC_RENDERSTATE, D3DRS_STENCILPASS, "D3DRS_STENCILPASS"},
254     {SC_RENDERSTATE, D3DRS_STENCILFUNC, "D3DRS_STENCILFUNC"},
255     {SC_RENDERSTATE, D3DRS_STENCILREF, "D3DRS_STENCILREF"},
256     {SC_RENDERSTATE, D3DRS_STENCILMASK, "D3DRS_STENCILMASK"},
257     {SC_RENDERSTATE, D3DRS_STENCILWRITEMASK, "D3DRS_STENCILWRITEMASK"},
258     {SC_RENDERSTATE, D3DRS_TEXTUREFACTOR, "D3DRS_TEXTUREFACTOR"},
259     {SC_RENDERSTATE, D3DRS_WRAP0, "D3DRS_WRAP0"},
260     {SC_RENDERSTATE, D3DRS_WRAP1, "D3DRS_WRAP1"}, /* 0x20 */
261     {SC_RENDERSTATE, D3DRS_WRAP2, "D3DRS_WRAP2"},
262     {SC_RENDERSTATE, D3DRS_WRAP3, "D3DRS_WRAP3"},
263     {SC_RENDERSTATE, D3DRS_WRAP4, "D3DRS_WRAP4"},
264     {SC_RENDERSTATE, D3DRS_WRAP5, "D3DRS_WRAP5"},
265     {SC_RENDERSTATE, D3DRS_WRAP6, "D3DRS_WRAP6"},
266     {SC_RENDERSTATE, D3DRS_WRAP7, "D3DRS_WRAP7"},
267     {SC_RENDERSTATE, D3DRS_WRAP8, "D3DRS_WRAP8"},
268     {SC_RENDERSTATE, D3DRS_WRAP9, "D3DRS_WRAP9"},
269     {SC_RENDERSTATE, D3DRS_WRAP10, "D3DRS_WRAP10"},
270     {SC_RENDERSTATE, D3DRS_WRAP11, "D3DRS_WRAP11"},
271     {SC_RENDERSTATE, D3DRS_WRAP12, "D3DRS_WRAP12"},
272     {SC_RENDERSTATE, D3DRS_WRAP13, "D3DRS_WRAP13"},
273     {SC_RENDERSTATE, D3DRS_WRAP14, "D3DRS_WRAP14"},
274     {SC_RENDERSTATE, D3DRS_WRAP15, "D3DRS_WRAP15"},
275     {SC_RENDERSTATE, D3DRS_CLIPPING, "D3DRS_CLIPPING"},
276     {SC_RENDERSTATE, D3DRS_LIGHTING, "D3DRS_LIGHTING"}, /* 0x30 */
277     {SC_RENDERSTATE, D3DRS_AMBIENT, "D3DRS_AMBIENT"},
278     {SC_RENDERSTATE, D3DRS_FOGVERTEXMODE, "D3DRS_FOGVERTEXMODE"},
279     {SC_RENDERSTATE, D3DRS_COLORVERTEX, "D3DRS_COLORVERTEX"},
280     {SC_RENDERSTATE, D3DRS_LOCALVIEWER, "D3DRS_LOCALVIEWER"},
281     {SC_RENDERSTATE, D3DRS_NORMALIZENORMALS, "D3DRS_NORMALIZENORMALS"},
282     {SC_RENDERSTATE, D3DRS_DIFFUSEMATERIALSOURCE, "D3DRS_DIFFUSEMATERIALSOURCE"},
283     {SC_RENDERSTATE, D3DRS_SPECULARMATERIALSOURCE, "D3DRS_SPECULARMATERIALSOURCE"},
284     {SC_RENDERSTATE, D3DRS_AMBIENTMATERIALSOURCE, "D3DRS_AMBIENTMATERIALSOURCE"},
285     {SC_RENDERSTATE, D3DRS_EMISSIVEMATERIALSOURCE, "D3DRS_EMISSIVEMATERIALSOURCE"},
286     {SC_RENDERSTATE, D3DRS_VERTEXBLEND, "D3DRS_VERTEXBLEND"},
287     {SC_RENDERSTATE, D3DRS_CLIPPLANEENABLE, "D3DRS_CLIPPLANEENABLE"},
288     {SC_RENDERSTATE, D3DRS_POINTSIZE, "D3DRS_POINTSIZE"},
289     {SC_RENDERSTATE, D3DRS_POINTSIZE_MIN, "D3DRS_POINTSIZE_MIN"},
290     {SC_RENDERSTATE, D3DRS_POINTSIZE_MAX, "D3DRS_POINTSIZE_MAX"},
291     {SC_RENDERSTATE, D3DRS_POINTSPRITEENABLE, "D3DRS_POINTSPRITEENABLE"},
292     {SC_RENDERSTATE, D3DRS_POINTSCALEENABLE, "D3DRS_POINTSCALEENABLE"}, /* 0x40 */
293     {SC_RENDERSTATE, D3DRS_POINTSCALE_A, "D3DRS_POINTSCALE_A"},
294     {SC_RENDERSTATE, D3DRS_POINTSCALE_B, "D3DRS_POINTSCALE_B"},
295     {SC_RENDERSTATE, D3DRS_POINTSCALE_C, "D3DRS_POINTSCALE_C"},
296     {SC_RENDERSTATE, D3DRS_MULTISAMPLEANTIALIAS, "D3DRS_MULTISAMPLEANTIALIAS"},
297     {SC_RENDERSTATE, D3DRS_MULTISAMPLEMASK, "D3DRS_MULTISAMPLEMASK"},
298     {SC_RENDERSTATE, D3DRS_PATCHEDGESTYLE, "D3DRS_PATCHEDGESTYLE"},
299     {SC_RENDERSTATE, D3DRS_DEBUGMONITORTOKEN, "D3DRS_DEBUGMONITORTOKEN"},
300     {SC_RENDERSTATE, D3DRS_INDEXEDVERTEXBLENDENABLE, "D3DRS_INDEXEDVERTEXBLENDENABLE"},
301     {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE, "D3DRS_COLORWRITEENABLE"},
302     {SC_RENDERSTATE, D3DRS_TWEENFACTOR, "D3DRS_TWEENFACTOR"},
303     {SC_RENDERSTATE, D3DRS_BLENDOP, "D3DRS_BLENDOP"},
304     {SC_RENDERSTATE, D3DRS_POSITIONDEGREE, "D3DRS_POSITIONDEGREE"},
305     {SC_RENDERSTATE, D3DRS_NORMALDEGREE, "D3DRS_NORMALDEGREE"},
306     {SC_RENDERSTATE, D3DRS_SCISSORTESTENABLE, "D3DRS_SCISSORTESTENABLE"},
307     {SC_RENDERSTATE, D3DRS_SLOPESCALEDEPTHBIAS, "D3DRS_SLOPESCALEDEPTHBIAS"},
308     {SC_RENDERSTATE, D3DRS_ANTIALIASEDLINEENABLE, "D3DRS_ANTIALIASEDLINEENABLE"}, /* 0x50 */
309     {SC_RENDERSTATE, D3DRS_MINTESSELLATIONLEVEL, "D3DRS_MINTESSELLATIONLEVEL"},
310     {SC_RENDERSTATE, D3DRS_MAXTESSELLATIONLEVEL, "D3DRS_MAXTESSELLATIONLEVEL"},
311     {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_X, "D3DRS_ADAPTIVETESS_X"},
312     {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_Y, "D3DRS_ADAPTIVETESS_Y"},
313     {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_Z, "D3DRS_ADAPTIVETESS_Z"},
314     {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_W, "D3DRS_ADAPTIVETESS_W"},
315     {SC_RENDERSTATE, D3DRS_ENABLEADAPTIVETESSELLATION, "D3DRS_ENABLEADAPTIVETESSELLATION"},
316     {SC_RENDERSTATE, D3DRS_TWOSIDEDSTENCILMODE, "D3DRS_TWOSIDEDSTENCILMODE"},
317     {SC_RENDERSTATE, D3DRS_CCW_STENCILFAIL, "D3DRS_CCW_STENCILFAIL"},
318     {SC_RENDERSTATE, D3DRS_CCW_STENCILZFAIL, "D3DRS_CCW_STENCILZFAIL"},
319     {SC_RENDERSTATE, D3DRS_CCW_STENCILPASS, "D3DRS_CCW_STENCILPASS"},
320     {SC_RENDERSTATE, D3DRS_CCW_STENCILFUNC, "D3DRS_CCW_STENCILFUNC"},
321     {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE1, "D3DRS_COLORWRITEENABLE1"},
322     {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE2, "D3DRS_COLORWRITEENABLE2"},
323     {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE3, "D3DRS_COLORWRITEENABLE3"},
324     {SC_RENDERSTATE, D3DRS_BLENDFACTOR, "D3DRS_BLENDFACTOR"}, /* 0x60 */
325     {SC_RENDERSTATE, D3DRS_SRGBWRITEENABLE, "D3DRS_SRGBWRITEENABLE"},
326     {SC_RENDERSTATE, D3DRS_DEPTHBIAS, "D3DRS_DEPTHBIAS"},
327     {SC_RENDERSTATE, D3DRS_SEPARATEALPHABLENDENABLE, "D3DRS_SEPARATEALPHABLENDENABLE"},
328     {SC_RENDERSTATE, D3DRS_SRCBLENDALPHA, "D3DRS_SRCBLENDALPHA"},
329     {SC_RENDERSTATE, D3DRS_DESTBLENDALPHA, "D3DRS_DESTBLENDALPHA"},
330     {SC_RENDERSTATE, D3DRS_BLENDOPALPHA, "D3DRS_BLENDOPALPHA"},
331     /* Texture stages */
332     {SC_TEXTURESTAGE, D3DTSS_COLOROP, "D3DTSS_COLOROP"},
333     {SC_TEXTURESTAGE, D3DTSS_COLORARG0, "D3DTSS_COLORARG0"},
334     {SC_TEXTURESTAGE, D3DTSS_COLORARG1, "D3DTSS_COLORARG1"},
335     {SC_TEXTURESTAGE, D3DTSS_COLORARG2, "D3DTSS_COLORARG2"},
336     {SC_TEXTURESTAGE, D3DTSS_ALPHAOP, "D3DTSS_ALPHAOP"},
337     {SC_TEXTURESTAGE, D3DTSS_ALPHAARG0, "D3DTSS_ALPHAARG0"},
338     {SC_TEXTURESTAGE, D3DTSS_ALPHAARG1, "D3DTSS_ALPHAARG1"},
339     {SC_TEXTURESTAGE, D3DTSS_ALPHAARG2, "D3DTSS_ALPHAARG2"},
340     {SC_TEXTURESTAGE, D3DTSS_RESULTARG, "D3DTSS_RESULTARG"},
341     {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT00, "D3DTSS_BUMPENVMAT00"}, /* 0x70 */
342     {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT01, "D3DTSS_BUMPENVMAT01"},
343     {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT10, "D3DTSS_BUMPENVMAT10"},
344     {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT11, "D3DTSS_BUMPENVMAT11"},
345     {SC_TEXTURESTAGE, D3DTSS_TEXCOORDINDEX, "D3DTSS_TEXCOORDINDEX"},
346     {SC_TEXTURESTAGE, D3DTSS_BUMPENVLSCALE, "D3DTSS_BUMPENVLSCALE"},
347     {SC_TEXTURESTAGE, D3DTSS_BUMPENVLOFFSET, "D3DTSS_BUMPENVLOFFSET"},
348     {SC_TEXTURESTAGE, D3DTSS_TEXTURETRANSFORMFLAGS, "D3DTSS_TEXTURETRANSFORMFLAGS"},
349     {SC_TEXTURESTAGE, D3DTSS_CONSTANT, "D3DTSS_CONSTANT"},
350     /* NPatchMode */
351     {SC_NPATCHMODE, 0, "NPatchMode"},
352     /* FVF */
353     {SC_FVF, 0, "FVF"},
354     /* Transform */
355     {SC_TRANSFORM, D3DTS_PROJECTION, "D3DTS_PROJECTION"},
356     {SC_TRANSFORM, D3DTS_VIEW, "D3DTS_VIEW"},
357     {SC_TRANSFORM, D3DTS_WORLD, "D3DTS_WORLD"},
358     {SC_TRANSFORM, D3DTS_TEXTURE0, "D3DTS_TEXTURE0"},
359     /* Material */
360     {SC_MATERIAL, MT_DIFFUSE, "MaterialDiffuse"},
361     {SC_MATERIAL, MT_AMBIENT, "MaterialAmbient"}, /* 0x80 */
362     {SC_MATERIAL, MT_SPECULAR, "MaterialSpecular"},
363     {SC_MATERIAL, MT_EMISSIVE, "MaterialEmissive"},
364     {SC_MATERIAL, MT_POWER, "MaterialPower"},
365     /* Light */
366     {SC_LIGHT, LT_TYPE, "LightType"},
367     {SC_LIGHT, LT_DIFFUSE, "LightDiffuse"},
368     {SC_LIGHT, LT_SPECULAR, "LightSpecular"},
369     {SC_LIGHT, LT_AMBIENT, "LightAmbient"},
370     {SC_LIGHT, LT_POSITION, "LightPosition"},
371     {SC_LIGHT, LT_DIRECTION, "LightDirection"},
372     {SC_LIGHT, LT_RANGE, "LightRange"},
373     {SC_LIGHT, LT_FALLOFF, "LightFallOff"},
374     {SC_LIGHT, LT_ATTENUATION0, "LightAttenuation0"},
375     {SC_LIGHT, LT_ATTENUATION1, "LightAttenuation1"},
376     {SC_LIGHT, LT_ATTENUATION2, "LightAttenuation2"},
377     {SC_LIGHT, LT_THETA, "LightTheta"},
378     {SC_LIGHT, LT_PHI, "LightPhi"}, /* 0x90 */
379     /* Lightenable */
380     {SC_LIGHTENABLE, 0, "LightEnable"},
381     /* Vertexshader */
382     {SC_VERTEXSHADER, 0, "Vertexshader"},
383     /* Pixelshader */
384     {SC_PIXELSHADER, 0, "Pixelshader"},
385     /* Shader constants */
386     {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstantF"},
387     {SC_SHADERCONST, SCT_VSBOOL, "VertexShaderConstantB"},
388     {SC_SHADERCONST, SCT_VSINT, "VertexShaderConstantI"},
389     {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant"},
390     {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant1"},
391     {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant2"},
392     {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant3"},
393     {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant4"},
394     {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstantF"},
395     {SC_SHADERCONST, SCT_PSBOOL, "PixelShaderConstantB"},
396     {SC_SHADERCONST, SCT_PSINT, "PixelShaderConstantI"},
397     {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant"},
398     {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant1"}, /* 0xa0 */
399     {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant2"},
400     {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant3"},
401     {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant4"},
402     /* Texture */
403     {SC_TEXTURE, 0, "Texture"},
404     /* Sampler states */
405     {SC_SAMPLERSTATE, D3DSAMP_ADDRESSU, "AddressU"},
406     {SC_SAMPLERSTATE, D3DSAMP_ADDRESSV, "AddressV"},
407     {SC_SAMPLERSTATE, D3DSAMP_ADDRESSW, "AddressW"},
408     {SC_SAMPLERSTATE, D3DSAMP_BORDERCOLOR, "BorderColor"},
409     {SC_SAMPLERSTATE, D3DSAMP_MAGFILTER, "MagFilter"},
410     {SC_SAMPLERSTATE, D3DSAMP_MINFILTER, "MinFilter"},
411     {SC_SAMPLERSTATE, D3DSAMP_MIPFILTER, "MipFilter"},
412     {SC_SAMPLERSTATE, D3DSAMP_MIPMAPLODBIAS, "MipMapLodBias"},
413     {SC_SAMPLERSTATE, D3DSAMP_MAXMIPLEVEL, "MaxMipLevel"},
414     {SC_SAMPLERSTATE, D3DSAMP_MAXANISOTROPY, "MaxAnisotropy"},
415     {SC_SAMPLERSTATE, D3DSAMP_SRGBTEXTURE, "SRGBTexture"},
416     {SC_SAMPLERSTATE, D3DSAMP_ELEMENTINDEX, "ElementIndex"}, /* 0xb0 */
417     {SC_SAMPLERSTATE, D3DSAMP_DMAPOFFSET, "DMAPOffset"},
418     /* Set sampler */
419     {SC_SETSAMPLER, 0, "Sampler"},
420 };
421 
422 static inline void read_dword(const char **ptr, DWORD *d)
423 {
424     memcpy(d, *ptr, sizeof(*d));
425     *ptr += sizeof(*d);
426 }
427 
428 static void skip_dword_unknown(const char **ptr, unsigned int count)
429 {
430     unsigned int i;
431     DWORD d;
432 
433     WARN("Skipping %u unknown DWORDs:\n", count);
434     for (i = 0; i < count; ++i)
435     {
436         read_dword(ptr, &d);
437         WARN("\t0x%08x\n", d);
438     }
439 }
440 
441 static inline D3DXHANDLE get_parameter_handle(struct d3dx_parameter *parameter)
442 {
443     return (D3DXHANDLE)parameter;
444 }
445 
446 static inline D3DXHANDLE get_technique_handle(struct d3dx_technique *technique)
447 {
448     return (D3DXHANDLE)technique;
449 }
450 
451 static inline D3DXHANDLE get_pass_handle(struct d3dx_pass *pass)
452 {
453     return (D3DXHANDLE)pass;
454 }
455 
456 static struct d3dx_technique *get_technique_by_name(struct d3dx_effect *effect, const char *name)
457 {
458     unsigned int i;
459 
460     if (!name) return NULL;
461 
462     for (i = 0; i < effect->technique_count; ++i)
463     {
464         if (!strcmp(effect->techniques[i].name, name))
465             return &effect->techniques[i];
466     }
467 
468     return NULL;
469 }
470 
471 static struct d3dx_technique *get_valid_technique(struct d3dx_effect *effect, D3DXHANDLE technique)
472 {
473     unsigned int i;
474 
475     for (i = 0; i < effect->technique_count; ++i)
476     {
477         if (get_technique_handle(&effect->techniques[i]) == technique)
478             return &effect->techniques[i];
479     }
480 
481     return get_technique_by_name(effect, technique);
482 }
483 
484 static struct d3dx_pass *get_valid_pass(struct d3dx_effect *effect, D3DXHANDLE pass)
485 {
486     unsigned int i, k;
487 
488     for (i = 0; i < effect->technique_count; ++i)
489     {
490         struct d3dx_technique *technique = &effect->techniques[i];
491 
492         for (k = 0; k < technique->pass_count; ++k)
493         {
494             if (get_pass_handle(&technique->passes[k]) == pass)
495                 return &technique->passes[k];
496         }
497     }
498 
499     return NULL;
500 }
501 
502 static struct d3dx_parameter *get_valid_parameter(struct d3dx_effect *effect, D3DXHANDLE parameter)
503 {
504     struct d3dx_parameter *handle_param = (struct d3dx_parameter *)parameter;
505 
506     if (handle_param && !strncmp(handle_param->magic_string, parameter_magic_string,
507             sizeof(parameter_magic_string)))
508         return handle_param;
509 
510     return effect->flags & D3DXFX_LARGEADDRESSAWARE ? NULL : get_parameter_by_name(effect, NULL, parameter);
511 }
512 
513 static void free_state(struct d3dx_state *state)
514 {
515     free_parameter(&state->parameter, FALSE, FALSE);
516 }
517 
518 static void free_object(struct d3dx_object *object)
519 {
520     HeapFree(GetProcessHeap(), 0, object->data);
521 }
522 
523 static void free_sampler(struct d3dx_sampler *sampler)
524 {
525     UINT i;
526 
527     for (i = 0; i < sampler->state_count; ++i)
528     {
529         free_state(&sampler->states[i]);
530     }
531     HeapFree(GetProcessHeap(), 0, sampler->states);
532 }
533 
534 static void d3dx_pool_release_shared_parameter(struct d3dx_top_level_parameter *param);
535 
536 static void free_parameter_data(struct d3dx_parameter *param, BOOL child)
537 {
538     if (!param->data)
539         return;
540     if (param->class == D3DXPC_OBJECT && !param->element_count)
541     {
542         switch (param->type)
543         {
544             case D3DXPT_STRING:
545                 HeapFree(GetProcessHeap(), 0, *(char **)param->data);
546                 break;
547 
548             case D3DXPT_TEXTURE:
549             case D3DXPT_TEXTURE1D:
550             case D3DXPT_TEXTURE2D:
551             case D3DXPT_TEXTURE3D:
552             case D3DXPT_TEXTURECUBE:
553             case D3DXPT_PIXELSHADER:
554             case D3DXPT_VERTEXSHADER:
555                 if (*(IUnknown **)param->data) IUnknown_Release(*(IUnknown **)param->data);
556                 break;
557 
558             case D3DXPT_SAMPLER:
559             case D3DXPT_SAMPLER1D:
560             case D3DXPT_SAMPLER2D:
561             case D3DXPT_SAMPLER3D:
562             case D3DXPT_SAMPLERCUBE:
563                 free_sampler((struct d3dx_sampler *)param->data);
564                 break;
565 
566             default:
567                 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(param->type));
568                 break;
569         }
570     }
571     if (!child)
572         HeapFree(GetProcessHeap(), 0, param->data);
573 }
574 
575 static void free_parameter(struct d3dx_parameter *param, BOOL element, BOOL child)
576 {
577     unsigned int i;
578 
579     TRACE("Free parameter %p, name %s, type %s, element %#x, child %#x.\n", param, param->name,
580             debug_d3dxparameter_type(param->type), element, child);
581 
582     if (param->param_eval)
583         d3dx_free_param_eval(param->param_eval);
584 
585     if (param->members)
586     {
587         unsigned int count = param->element_count ? param->element_count : param->member_count;
588 
589         for (i = 0; i < count; ++i)
590             free_parameter(&param->members[i], param->element_count != 0, TRUE);
591         HeapFree(GetProcessHeap(), 0, param->members);
592     }
593 
594     free_parameter_data(param, child);
595 
596     /* only the parent has to release name and semantic */
597     if (!element)
598     {
599         HeapFree(GetProcessHeap(), 0, param->name);
600         HeapFree(GetProcessHeap(), 0, param->semantic);
601     }
602 }
603 
604 static void free_top_level_parameter(struct d3dx_top_level_parameter *param)
605 {
606     if (param->annotations)
607     {
608         unsigned int i;
609 
610         for (i = 0; i < param->annotation_count; ++i)
611             free_parameter(&param->annotations[i], FALSE, FALSE);
612         HeapFree(GetProcessHeap(), 0, param->annotations);
613     }
614     d3dx_pool_release_shared_parameter(param);
615     free_parameter(&param->param, FALSE, FALSE);
616 }
617 
618 static void free_pass(struct d3dx_pass *pass)
619 {
620     unsigned int i;
621 
622     TRACE("Free pass %p\n", pass);
623 
624     if (!pass)
625         return;
626 
627     if (pass->annotations)
628     {
629         for (i = 0; i < pass->annotation_count; ++i)
630             free_parameter(&pass->annotations[i], FALSE, FALSE);
631         HeapFree(GetProcessHeap(), 0, pass->annotations);
632         pass->annotations = NULL;
633     }
634 
635     if (pass->states)
636     {
637         for (i = 0; i < pass->state_count; ++i)
638             free_state(&pass->states[i]);
639         HeapFree(GetProcessHeap(), 0, pass->states);
640         pass->states = NULL;
641     }
642 
643     HeapFree(GetProcessHeap(), 0, pass->name);
644     pass->name = NULL;
645 }
646 
647 static void free_technique(struct d3dx_technique *technique)
648 {
649     unsigned int i;
650 
651     TRACE("Free technique %p\n", technique);
652 
653     if (!technique)
654         return;
655 
656     if (technique->saved_state)
657     {
658         IDirect3DStateBlock9_Release(technique->saved_state);
659         technique->saved_state = NULL;
660     }
661 
662     if (technique->annotations)
663     {
664         for (i = 0; i < technique->annotation_count; ++i)
665             free_parameter(&technique->annotations[i], FALSE, FALSE);
666         HeapFree(GetProcessHeap(), 0, technique->annotations);
667         technique->annotations = NULL;
668     }
669 
670     if (technique->passes)
671     {
672         for (i = 0; i < technique->pass_count; ++i)
673             free_pass(&technique->passes[i]);
674         HeapFree(GetProcessHeap(), 0, technique->passes);
675         technique->passes = NULL;
676     }
677 
678     HeapFree(GetProcessHeap(), 0, technique->name);
679     technique->name = NULL;
680 }
681 
682 static void d3dx_effect_cleanup(struct d3dx_effect *effect)
683 {
684     ID3DXEffectPool *pool;
685     unsigned int i;
686 
687     TRACE("effect %p.\n", effect);
688 
689     heap_free(effect->full_name_tmp);
690 
691     if (effect->parameters)
692     {
693         for (i = 0; i < effect->parameter_count; ++i)
694             free_top_level_parameter(&effect->parameters[i]);
695         heap_free(effect->parameters);
696     }
697 
698     if (effect->techniques)
699     {
700         for (i = 0; i < effect->technique_count; ++i)
701             free_technique(&effect->techniques[i]);
702         heap_free(effect->techniques);
703     }
704 
705     if (effect->objects)
706     {
707         for (i = 0; i < effect->object_count; ++i)
708             free_object(&effect->objects[i]);
709         heap_free(effect->objects);
710     }
711 
712     if (effect->pool)
713     {
714         pool = &effect->pool->ID3DXEffectPool_iface;
715         pool->lpVtbl->Release(pool);
716     }
717 
718     if (effect->manager)
719         IUnknown_Release(effect->manager);
720 
721     IDirect3DDevice9_Release(effect->device);
722     heap_free(effect);
723 }
724 
725 static void get_vector(struct d3dx_parameter *param, D3DXVECTOR4 *vector)
726 {
727     UINT i;
728 
729     for (i = 0; i < 4; ++i)
730     {
731         if (i < param->columns)
732             set_number((FLOAT *)vector + i, D3DXPT_FLOAT, (DWORD *)param->data + i, param->type);
733         else
734             ((FLOAT *)vector)[i] = 0.0f;
735     }
736 }
737 
738 static void set_vector(struct d3dx_parameter *param, const D3DXVECTOR4 *vector)
739 {
740     UINT i;
741 
742     for (i = 0; i < param->columns; ++i)
743     {
744         set_number((FLOAT *)param->data + i, param->type, (FLOAT *)vector + i, D3DXPT_FLOAT);
745     }
746 }
747 
748 static void get_matrix(struct d3dx_parameter *param, D3DXMATRIX *matrix, BOOL transpose)
749 {
750     UINT i, k;
751 
752     for (i = 0; i < 4; ++i)
753     {
754         for (k = 0; k < 4; ++k)
755         {
756             FLOAT *tmp = transpose ? (FLOAT *)&matrix->u.m[k][i] : (FLOAT *)&matrix->u.m[i][k];
757 
758             if ((i < param->rows) && (k < param->columns))
759                 set_number(tmp, D3DXPT_FLOAT, (DWORD *)param->data + i * param->columns + k, param->type);
760             else
761                 *tmp = 0.0f;
762         }
763     }
764 }
765 
766 static void set_matrix(struct d3dx_parameter *param, const D3DXMATRIX *matrix)
767 {
768     UINT i, k;
769 
770     if (param->type == D3DXPT_FLOAT)
771     {
772         if (param->columns == 4)
773             memcpy(param->data, matrix->u.m, param->rows * 4 * sizeof(float));
774         else
775             for (i = 0; i < param->rows; ++i)
776                 memcpy((float *)param->data + i * param->columns, matrix->u.m + i, param->columns * sizeof(float));
777         return;
778     }
779 
780     for (i = 0; i < param->rows; ++i)
781     {
782         for (k = 0; k < param->columns; ++k)
783         {
784             set_number((FLOAT *)param->data + i * param->columns + k, param->type,
785                     &matrix->u.m[i][k], D3DXPT_FLOAT);
786         }
787     }
788 }
789 
790 static void set_matrix_transpose(struct d3dx_parameter *param, const D3DXMATRIX *matrix)
791 {
792     UINT i, k;
793 
794     for (i = 0; i < param->rows; ++i)
795     {
796         for (k = 0; k < param->columns; ++k)
797         {
798             set_number((FLOAT *)param->data + i * param->columns + k, param->type,
799                     &matrix->u.m[k][i], D3DXPT_FLOAT);
800         }
801     }
802 }
803 
804 static struct d3dx_parameter *get_parameter_element_by_name(struct d3dx_effect *effect,
805         struct d3dx_parameter *parameter, const char *name)
806 {
807     UINT element;
808     struct d3dx_parameter *temp_parameter;
809     const char *part;
810 
811     TRACE("parameter %p, name %s\n", parameter, debugstr_a(name));
812 
813     if (!name || !*name) return NULL;
814 
815     element = atoi(name);
816     part = strchr(name, ']') + 1;
817 
818     /* check for empty [] && element range */
819     if ((part - name) > 1 && parameter->element_count > element)
820     {
821         temp_parameter = &parameter->members[element];
822 
823         switch (*part++)
824         {
825             case '.':
826                 return get_parameter_by_name(effect, temp_parameter, part);
827 
828             case '\0':
829                 TRACE("Returning parameter %p\n", temp_parameter);
830                 return temp_parameter;
831 
832             default:
833                 FIXME("Unhandled case \"%c\"\n", *--part);
834                 break;
835         }
836     }
837 
838     TRACE("Parameter not found\n");
839     return NULL;
840 }
841 
842 static struct d3dx_parameter *get_annotation_by_name(struct d3dx_effect *effect, unsigned int count,
843         struct d3dx_parameter *annotations, const char *name)
844 {
845     UINT i, length;
846     struct d3dx_parameter *temp_parameter;
847     const char *part;
848 
849     TRACE("count %u, annotations %p, name %s\n", count, annotations, debugstr_a(name));
850 
851     if (!name || !*name) return NULL;
852 
853     length = strcspn( name, "[.@" );
854     part = name + length;
855 
856     for (i = 0; i < count; ++i)
857     {
858         temp_parameter = &annotations[i];
859 
860         if (!strcmp(temp_parameter->name, name))
861         {
862             TRACE("Returning annotation %p\n", temp_parameter);
863             return temp_parameter;
864         }
865         else if (strlen(temp_parameter->name) == length && !strncmp(temp_parameter->name, name, length))
866         {
867             switch (*part++)
868             {
869                 case '.':
870                     return get_parameter_by_name(effect, temp_parameter, part);
871 
872                 case '[':
873                     return get_parameter_element_by_name(effect, temp_parameter, part);
874 
875                 default:
876                     FIXME("Unhandled case \"%c\"\n", *--part);
877                     break;
878             }
879         }
880     }
881 
882     TRACE("Annotation not found\n");
883     return NULL;
884 }
885 
886 struct d3dx_parameter *get_parameter_by_name(struct d3dx_effect* effect,
887         struct d3dx_parameter *parameter, const char *name)
888 {
889     struct d3dx_parameter *temp_parameter;
890     unsigned int name_len, param_name_len;
891     unsigned int i, count, length;
892     struct wine_rb_entry *entry;
893     unsigned int full_name_size;
894     const char *part;
895     char *full_name;
896 
897     TRACE("effect %p, parameter %p, name %s.\n", effect, parameter, debugstr_a(name));
898 
899     if (!name || !*name) return NULL;
900 
901     if (!parameter)
902     {
903         if ((entry = wine_rb_get(&effect->param_tree, name)))
904             return WINE_RB_ENTRY_VALUE(entry, struct d3dx_parameter, rb_entry);
905         return NULL;
906     }
907 
908     if (parameter->full_name)
909     {
910         name_len = strlen(name);
911         param_name_len = strlen(parameter->full_name);
912         full_name_size = name_len + param_name_len + 2;
913         if (effect->full_name_tmp_size < full_name_size)
914         {
915             if (!(full_name = heap_realloc(effect->full_name_tmp, full_name_size)))
916             {
917                 ERR("Out of memory.\n");
918                 return NULL;
919             }
920             effect->full_name_tmp = full_name;
921             effect->full_name_tmp_size = full_name_size;
922         }
923         else
924         {
925             full_name = effect->full_name_tmp;
926         }
927         memcpy(full_name, parameter->full_name, param_name_len);
928         full_name[param_name_len] = '.';
929         memcpy(full_name + param_name_len + 1, name, name_len);
930         full_name[param_name_len + 1 + name_len] = 0;
931 
932         if ((entry = wine_rb_get(&effect->param_tree, full_name)))
933             return WINE_RB_ENTRY_VALUE(entry, struct d3dx_parameter, rb_entry);
934         return NULL;
935     }
936 
937     /* Pass / technique annotations are not stored in the parameters tree,
938      * do a linear search. */
939     count = parameter->member_count;
940 
941     length = strcspn( name, "[." );
942     part = name + length;
943 
944     for (i = 0; i < count; i++)
945     {
946         temp_parameter = &parameter->members[i];
947 
948         if (!strcmp(temp_parameter->name, name))
949         {
950             TRACE("Returning parameter %p\n", temp_parameter);
951             return temp_parameter;
952         }
953         else if (strlen(temp_parameter->name) == length && !strncmp(temp_parameter->name, name, length))
954         {
955             switch (*part++)
956             {
957                 case '.':
958                     return get_parameter_by_name(effect, temp_parameter, part);
959 
960                 case '[':
961                     return get_parameter_element_by_name(effect, temp_parameter, part);
962 
963                 default:
964                     FIXME("Unhandled case \"%c\"\n", *--part);
965                     break;
966             }
967         }
968     }
969 
970     TRACE("Parameter not found\n");
971     return NULL;
972 }
973 
974 static inline DWORD d3dx9_effect_version(DWORD major, DWORD minor)
975 {
976     return (0xfeff0000 | ((major) << 8) | (minor));
977 }
978 
979 static HRESULT d3dx9_get_param_value_ptr(struct d3dx_pass *pass, struct d3dx_state *state,
980         void **param_value, struct d3dx_parameter **out_param,
981         BOOL update_all, BOOL *param_dirty)
982 {
983     struct d3dx_parameter *param = &state->parameter;
984 
985     *param_value = NULL;
986     *out_param = NULL;
987     *param_dirty = FALSE;
988 
989     switch (state->type)
990     {
991         case ST_PARAMETER:
992             param = state->referenced_param;
993             *param_dirty = is_param_dirty(param, pass->update_version);
994             /* fallthrough */
995         case ST_CONSTANT:
996             *out_param = param;
997             *param_value = param->data;
998             return D3D_OK;
999         case ST_ARRAY_SELECTOR:
1000         {
1001             unsigned int array_idx;
1002             static const struct d3dx_parameter array_idx_param =
1003                 {"", NULL, NULL, NULL, NULL, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 0, 0, 0, sizeof(array_idx)};
1004             HRESULT hr;
1005             struct d3dx_parameter *ref_param, *selected_param;
1006 
1007             if (!param->param_eval)
1008             {
1009                 FIXME("Preshader structure is null.\n");
1010                 return D3DERR_INVALIDCALL;
1011             }
1012             /* We override with the update_version of the pass because we want
1013              * to force index recomputation and check for out of bounds. */
1014             if (is_param_eval_input_dirty(param->param_eval, pass->update_version))
1015             {
1016                 if (FAILED(hr = d3dx_evaluate_parameter(param->param_eval, &array_idx_param, &array_idx)))
1017                     return hr;
1018             }
1019             else
1020             {
1021                 array_idx = state->index;
1022             }
1023             ref_param = state->referenced_param;
1024             TRACE("Array index %u, stored array index %u, element_count %u.\n", array_idx, state->index,
1025                     ref_param->element_count);
1026             /* According to the tests, native d3dx handles the case of array index evaluated to -1
1027              * in a specific way, always selecting first array element and not returning error. */
1028             if (array_idx == ~0u)
1029             {
1030                 WARN("Array index is -1, setting to 0.\n");
1031                 array_idx = 0;
1032             }
1033 
1034             if (array_idx >= ref_param->element_count)
1035             {
1036                 WARN("Computed array index %u is larger than array size %u.\n",
1037                         array_idx, ref_param->element_count);
1038                 return E_FAIL;
1039             }
1040             selected_param = &ref_param->members[array_idx];
1041             *param_dirty = state->index != array_idx || is_param_dirty(selected_param, pass->update_version);
1042             state->index = array_idx;
1043 
1044             *param_value = selected_param->data;
1045             *out_param = selected_param;
1046             return D3D_OK;
1047         }
1048         case ST_FXLC:
1049             if (param->param_eval)
1050             {
1051                 *out_param = param;
1052                 *param_value = param->data;
1053                 /* We check with the update_version of the pass because the
1054                  * same preshader might be used by both the vertex and the
1055                  * pixel shader (that can happen e.g. for sampler states). */
1056                 if (update_all || is_param_eval_input_dirty(param->param_eval, pass->update_version))
1057                 {
1058                     *param_dirty = TRUE;
1059                     return d3dx_evaluate_parameter(param->param_eval, param, *param_value);
1060                 }
1061                 else
1062                     return D3D_OK;
1063             }
1064             else
1065             {
1066                 FIXME("No preshader for FXLC parameter.\n");
1067                 return D3DERR_INVALIDCALL;
1068             }
1069     }
1070     return E_NOTIMPL;
1071 }
1072 
1073 static unsigned int get_annotation_from_object(struct d3dx_effect *effect, D3DXHANDLE object,
1074         struct d3dx_parameter **annotations)
1075 {
1076     struct d3dx_parameter *param = get_valid_parameter(effect, object);
1077     struct d3dx_pass *pass = get_valid_pass(effect, object);
1078     struct d3dx_technique *technique = get_valid_technique(effect, object);
1079 
1080     if (pass)
1081     {
1082         *annotations = pass->annotations;
1083         return pass->annotation_count;
1084     }
1085     else if (technique)
1086     {
1087         *annotations = technique->annotations;
1088         return technique->annotation_count;
1089     }
1090     else if (param)
1091     {
1092         if (is_top_level_parameter(param))
1093         {
1094             struct d3dx_top_level_parameter *top_param
1095                     = top_level_parameter_from_parameter(param);
1096 
1097             *annotations = top_param->annotations;
1098             return top_param->annotation_count;
1099         }
1100         else
1101         {
1102             *annotations = NULL;
1103             return 0;
1104         }
1105     }
1106     else
1107     {
1108         FIXME("Functions are not handled, yet!\n");
1109         return 0;
1110     }
1111 }
1112 
1113 static BOOL walk_parameter_tree(struct d3dx_parameter *param, walk_parameter_dep_func param_func,
1114         void *data)
1115 {
1116     unsigned int i;
1117     unsigned int member_count;
1118 
1119     if (param_func(data, param))
1120         return TRUE;
1121 
1122     member_count = param->element_count ? param->element_count : param->member_count;
1123     for (i = 0; i < member_count; ++i)
1124     {
1125         if (walk_parameter_tree(&param->members[i], param_func, data))
1126             return TRUE;
1127     }
1128     return FALSE;
1129 }
1130 
1131 static ULONG64 *get_version_counter_ptr(struct d3dx_effect *effect)
1132 {
1133     return effect->pool ? &effect->pool->version_counter : &effect->base_effect.version_counter;
1134 }
1135 
1136 static ULONG64 next_effect_update_version(struct d3dx_effect *effect)
1137 {
1138     return next_update_version(get_version_counter_ptr(effect));
1139 }
1140 
1141 static void set_dirty(struct d3dx_parameter *param)
1142 {
1143     struct d3dx_shared_data *shared_data;
1144     struct d3dx_top_level_parameter *top_param = param->top_level_param;
1145     ULONG64 new_update_version = next_update_version(top_param->version_counter);
1146 
1147     if ((shared_data = top_param->shared_data))
1148         shared_data->update_version = new_update_version;
1149     else
1150         top_param->update_version = new_update_version;
1151 }
1152 
1153 static HRESULT set_string(char **param_data, const char *string)
1154 {
1155     HeapFree(GetProcessHeap(), 0, *param_data);
1156     *param_data = HeapAlloc(GetProcessHeap(), 0, strlen(string) + 1);
1157     if (!*param_data)
1158     {
1159         ERR("Out of memory.\n");
1160         return E_OUTOFMEMORY;
1161     }
1162     strcpy(*param_data, string);
1163     return D3D_OK;
1164 }
1165 
1166 static void d3dx9_set_light_parameter(enum LIGHT_TYPE op, D3DLIGHT9 *light, void *value)
1167 {
1168     static const struct
1169     {
1170         unsigned int offset;
1171         const char *name;
1172     }
1173     light_tbl[] =
1174     {
1175         {FIELD_OFFSET(D3DLIGHT9, Type),         "LC_TYPE"},
1176         {FIELD_OFFSET(D3DLIGHT9, Diffuse),      "LT_DIFFUSE"},
1177         {FIELD_OFFSET(D3DLIGHT9, Specular),     "LT_SPECULAR"},
1178         {FIELD_OFFSET(D3DLIGHT9, Ambient),      "LT_AMBIENT"},
1179         {FIELD_OFFSET(D3DLIGHT9, Position),     "LT_POSITION"},
1180         {FIELD_OFFSET(D3DLIGHT9, Direction),    "LT_DIRECTION"},
1181         {FIELD_OFFSET(D3DLIGHT9, Range),        "LT_RANGE"},
1182         {FIELD_OFFSET(D3DLIGHT9, Falloff),      "LT_FALLOFF"},
1183         {FIELD_OFFSET(D3DLIGHT9, Attenuation0), "LT_ATTENUATION0"},
1184         {FIELD_OFFSET(D3DLIGHT9, Attenuation1), "LT_ATTENUATION1"},
1185         {FIELD_OFFSET(D3DLIGHT9, Attenuation2), "LT_ATTENUATION2"},
1186         {FIELD_OFFSET(D3DLIGHT9, Theta),        "LT_THETA"},
1187         {FIELD_OFFSET(D3DLIGHT9, Phi),          "LT_PHI"}
1188     };
1189     switch (op)
1190     {
1191         case LT_TYPE:
1192             TRACE("LT_TYPE %u.\n", *(D3DLIGHTTYPE *)value);
1193             light->Type = *(D3DLIGHTTYPE *)value;
1194             break;
1195         case LT_DIFFUSE:
1196         case LT_SPECULAR:
1197         case LT_AMBIENT:
1198         {
1199             D3DCOLORVALUE c = *(D3DCOLORVALUE *)value;
1200 
1201             TRACE("%s (%.8e %.8e %.8e %.8e).\n", light_tbl[op].name, c.r, c.g, c.b, c.a);
1202             *(D3DCOLORVALUE *)((BYTE *)light + light_tbl[op].offset) = c;
1203             break;
1204         }
1205         case LT_POSITION:
1206         case LT_DIRECTION:
1207         {
1208             D3DVECTOR v = *(D3DVECTOR *)value;
1209 
1210             TRACE("%s (%.8e %.8e %.8e).\n", light_tbl[op].name, v.x, v.y, v.z);
1211             *(D3DVECTOR *)((BYTE *)light + light_tbl[op].offset) = v;
1212             break;
1213         }
1214         case LT_RANGE:
1215         case LT_FALLOFF:
1216         case LT_ATTENUATION0:
1217         case LT_ATTENUATION1:
1218         case LT_ATTENUATION2:
1219         case LT_THETA:
1220         case LT_PHI:
1221         {
1222             float v = *(float *)value;
1223             TRACE("%s %.8e.\n", light_tbl[op].name, v);
1224             *(float *)((BYTE *)light + light_tbl[op].offset) = v;
1225             break;
1226         }
1227         default:
1228             WARN("Unknown light parameter %u.\n", op);
1229             break;
1230     }
1231 }
1232 
1233 static void d3dx9_set_material_parameter(enum MATERIAL_TYPE op, D3DMATERIAL9 *material, void *value)
1234 {
1235     static const struct
1236     {
1237         unsigned int offset;
1238         const char *name;
1239     }
1240     material_tbl[] =
1241     {
1242         {FIELD_OFFSET(D3DMATERIAL9, Diffuse),  "MT_DIFFUSE"},
1243         {FIELD_OFFSET(D3DMATERIAL9, Ambient),  "MT_AMBIENT"},
1244         {FIELD_OFFSET(D3DMATERIAL9, Specular), "MT_SPECULAR"},
1245         {FIELD_OFFSET(D3DMATERIAL9, Emissive), "MT_EMISSIVE"},
1246         {FIELD_OFFSET(D3DMATERIAL9, Power),    "MT_POWER"}
1247     };
1248 
1249     switch (op)
1250     {
1251         case MT_POWER:
1252         {
1253             float v = *(float *)value;
1254 
1255             TRACE("%s %.8e.\n", material_tbl[op].name, v);
1256             material->Power = v;
1257             break;
1258         }
1259         case MT_DIFFUSE:
1260         case MT_AMBIENT:
1261         case MT_SPECULAR:
1262         case MT_EMISSIVE:
1263         {
1264             D3DCOLORVALUE c = *(D3DCOLORVALUE *)value;
1265 
1266             TRACE("%s, value (%.8e %.8e %.8e %.8e).\n", material_tbl[op].name, c.r, c.g, c.b, c.a);
1267             *(D3DCOLORVALUE *)((BYTE *)material + material_tbl[op].offset) = c;
1268             break;
1269         }
1270         default:
1271             WARN("Unknown material parameter %u.\n", op);
1272             break;
1273     }
1274 }
1275 
1276 static HRESULT d3dx_set_shader_const_state(struct d3dx_effect *effect, enum SHADER_CONSTANT_TYPE op, UINT index,
1277         struct d3dx_parameter *param, void *value_ptr)
1278 {
1279     static const struct
1280     {
1281         D3DXPARAMETER_TYPE type;
1282         UINT elem_size;
1283         const char *name;
1284     }
1285     const_tbl[] =
1286     {
1287         {D3DXPT_FLOAT, sizeof(float) * 4, "SCT_VSFLOAT"},
1288         {D3DXPT_BOOL,  sizeof(BOOL),      "SCT_VSBOOL"},
1289         {D3DXPT_INT,   sizeof(int) * 4,   "SCT_VSINT"},
1290         {D3DXPT_FLOAT, sizeof(float) * 4, "SCT_PSFLOAT"},
1291         {D3DXPT_BOOL,  sizeof(BOOL),      "SCT_PSBOOL"},
1292         {D3DXPT_INT,   sizeof(int) * 4,   "SCT_PSINT"},
1293     };
1294 
1295     BOOL is_heap_buffer = FALSE;
1296     unsigned int element_count;
1297     void *buffer = value_ptr;
1298     D3DXVECTOR4 value;
1299     HRESULT ret;
1300 
1301     if (op < 0 || op > SCT_PSINT)
1302     {
1303         FIXME("Unknown op %u.\n", op);
1304         return D3DERR_INVALIDCALL;
1305     }
1306     element_count = param->bytes / const_tbl[op].elem_size;
1307     TRACE("%s, index %u, element_count %u.\n", const_tbl[op].name, index, element_count);
1308     if (param->type != const_tbl[op].type)
1309     {
1310         FIXME("Unexpected param type %u.\n", param->type);
1311         return D3DERR_INVALIDCALL;
1312     }
1313 
1314     if (param->bytes % const_tbl[op].elem_size || element_count > 1)
1315     {
1316         unsigned int param_data_size;
1317 
1318         TRACE("Parameter size %u, rows %u, cols %u.\n", param->bytes, param->rows, param->columns);
1319 
1320         if (param->bytes % const_tbl[op].elem_size)
1321             ++element_count;
1322         if (element_count > 1)
1323         {
1324             WARN("Setting %u elements.\n", element_count);
1325             buffer = HeapAlloc(GetProcessHeap(), 0, const_tbl[op].elem_size * element_count);
1326             if (!buffer)
1327             {
1328                 ERR("Out of memory.\n");
1329                 return E_OUTOFMEMORY;
1330             }
1331             is_heap_buffer = TRUE;
1332         }
1333         else
1334         {
1335             assert(const_tbl[op].elem_size <= sizeof(value));
1336             buffer = &value;
1337         }
1338         param_data_size = min(param->bytes, const_tbl[op].elem_size);
1339         memcpy(buffer, value_ptr, param_data_size);
1340         memset((unsigned char *)buffer + param_data_size, 0,
1341                 const_tbl[op].elem_size * element_count - param_data_size);
1342     }
1343 
1344     switch (op)
1345     {
1346         case SCT_VSFLOAT:
1347             ret = SET_D3D_STATE(effect, SetVertexShaderConstantF, index, (const float *)buffer, element_count);
1348             break;
1349         case SCT_VSBOOL:
1350             ret = SET_D3D_STATE(effect, SetVertexShaderConstantB, index, (const BOOL *)buffer, element_count);
1351             break;
1352         case SCT_VSINT:
1353             ret = SET_D3D_STATE(effect, SetVertexShaderConstantI, index, (const int *)buffer, element_count);
1354             break;
1355         case SCT_PSFLOAT:
1356             ret = SET_D3D_STATE(effect, SetPixelShaderConstantF, index, (const float *)buffer, element_count);
1357             break;
1358         case SCT_PSBOOL:
1359             ret = SET_D3D_STATE(effect, SetPixelShaderConstantB, index, (const BOOL *)buffer, element_count);
1360             break;
1361         case SCT_PSINT:
1362             ret = SET_D3D_STATE(effect, SetPixelShaderConstantI, index, (const int *)buffer, element_count);
1363             break;
1364         default:
1365             ret = D3DERR_INVALIDCALL;
1366             break;
1367     }
1368 
1369     if (is_heap_buffer)
1370         HeapFree(GetProcessHeap(), 0, buffer);
1371 
1372     return ret;
1373 }
1374 
1375 static HRESULT d3dx9_apply_state(struct d3dx_effect *effect, struct d3dx_pass *pass,
1376         struct d3dx_state *state, unsigned int parent_index, BOOL update_all);
1377 
1378 static HRESULT d3dx_set_shader_constants(struct d3dx_effect *effect, struct d3dx_pass *pass,
1379         struct d3dx_parameter *param, BOOL vs, BOOL update_all)
1380 {
1381     HRESULT hr, ret;
1382     struct d3dx_parameter **params;
1383     D3DXCONSTANT_DESC *cdesc;
1384     unsigned int parameters_count;
1385     unsigned int i, j;
1386 
1387     if (!param->param_eval)
1388     {
1389         FIXME("param_eval structure is null.\n");
1390         return D3DERR_INVALIDCALL;
1391     }
1392     if (FAILED(hr = d3dx_param_eval_set_shader_constants(effect->manager, effect->device,
1393             param->param_eval, update_all)))
1394         return hr;
1395     params = param->param_eval->shader_inputs.inputs_param;
1396     cdesc = param->param_eval->shader_inputs.inputs;
1397     parameters_count = param->param_eval->shader_inputs.input_count;
1398     ret = D3D_OK;
1399     for (i = 0; i < parameters_count; ++i)
1400     {
1401         if (params[i] && params[i]->class == D3DXPC_OBJECT && is_param_type_sampler(params[i]->type))
1402         {
1403             struct d3dx_sampler *sampler;
1404             unsigned int sampler_idx;
1405 
1406             for (sampler_idx = 0; sampler_idx < cdesc[i].RegisterCount; ++sampler_idx)
1407             {
1408                 sampler = params[i]->element_count ? params[i]->members[sampler_idx].data : params[i]->data;
1409                 TRACE("sampler %s, register index %u, state count %u.\n", debugstr_a(params[i]->name),
1410                         cdesc[i].RegisterIndex, sampler->state_count);
1411                 for (j = 0; j < sampler->state_count; ++j)
1412                 {
1413                     if (FAILED(hr = d3dx9_apply_state(effect, pass, &sampler->states[j],
1414                             cdesc[i].RegisterIndex + sampler_idx + (vs ? D3DVERTEXTEXTURESAMPLER0 : 0),
1415                             update_all)))
1416                         ret = hr;
1417                 }
1418             }
1419         }
1420     }
1421     return ret;
1422 }
1423 
1424 static HRESULT d3dx9_apply_state(struct d3dx_effect *effect, struct d3dx_pass *pass,
1425         struct d3dx_state *state, unsigned int parent_index, BOOL update_all)
1426 {
1427     struct d3dx_parameter *param;
1428     void *param_value;
1429     BOOL param_dirty;
1430     HRESULT hr;
1431 
1432     TRACE("operation %u, index %u, type %u.\n", state->operation, state->index, state->type);
1433 
1434     if (FAILED(hr = d3dx9_get_param_value_ptr(pass, state, &param_value, &param,
1435             update_all, &param_dirty)))
1436     {
1437         if (!update_all && hr == E_FAIL)
1438         {
1439             /* Native d3dx9 returns D3D_OK from CommitChanges() involving
1440              * out of bounds array access and does not touch the affected
1441              * states. */
1442             WARN("Returning D3D_OK on out of bounds array access.\n");
1443             return D3D_OK;
1444         }
1445         return hr;
1446     }
1447 
1448     if (!(update_all || param_dirty
1449             || state_table[state->operation].class == SC_VERTEXSHADER
1450             || state_table[state->operation].class == SC_PIXELSHADER
1451             || state_table[state->operation].class == SC_SETSAMPLER))
1452         return D3D_OK;
1453 
1454     switch (state_table[state->operation].class)
1455     {
1456         case SC_RENDERSTATE:
1457             TRACE("%s, operation %u, value %u.\n", state_table[state->operation].name,
1458                     state_table[state->operation].op, *(DWORD *)param_value);
1459             return SET_D3D_STATE(effect, SetRenderState, state_table[state->operation].op, *(DWORD *)param_value);
1460         case SC_FVF:
1461             TRACE("%s, value %#x.\n", state_table[state->operation].name, *(DWORD *)param_value);
1462             return SET_D3D_STATE(effect, SetFVF, *(DWORD *)param_value);
1463         case SC_TEXTURE:
1464         {
1465             UINT unit;
1466 
1467             unit = parent_index == ~0u ? state->index : parent_index;
1468             TRACE("%s, unit %u, value %p.\n", state_table[state->operation].name, unit,
1469                     *(IDirect3DBaseTexture9 **)param_value);
1470             return SET_D3D_STATE(effect, SetTexture, unit, *(IDirect3DBaseTexture9 **)param_value);
1471         }
1472         case SC_TEXTURESTAGE:
1473             TRACE("%s, stage %u, value %u.\n", state_table[state->operation].name, state->index, *(DWORD *)param_value);
1474             return SET_D3D_STATE(effect, SetTextureStageState, state->index,
1475                         state_table[state->operation].op, *(DWORD *)param_value);
1476         case SC_SETSAMPLER:
1477         {
1478             struct d3dx_sampler *sampler;
1479             HRESULT ret, hr;
1480             unsigned int i;
1481 
1482             sampler = (struct d3dx_sampler *)param_value;
1483             TRACE("%s, sampler %u, applying %u states.\n", state_table[state->operation].name, state->index,
1484                     sampler->state_count);
1485             ret = D3D_OK;
1486             for (i = 0; i < sampler->state_count; i++)
1487             {
1488                 if (FAILED(hr = d3dx9_apply_state(effect, pass, &sampler->states[i], state->index, update_all)))
1489                     ret = hr;
1490             }
1491             return ret;
1492         }
1493         case SC_SAMPLERSTATE:
1494         {
1495             UINT sampler;
1496 
1497             sampler = parent_index == ~0u ? state->index : parent_index;
1498             TRACE("%s, sampler %u, value %u.\n", state_table[state->operation].name, sampler, *(DWORD *)param_value);
1499             return SET_D3D_STATE(effect, SetSamplerState, sampler, state_table[state->operation].op,
1500                     *(DWORD *)param_value);
1501         }
1502         case SC_VERTEXSHADER:
1503             TRACE("%s, shader %p.\n", state_table[state->operation].name, *(IDirect3DVertexShader9 **)param_value);
1504             if ((update_all || param_dirty)
1505                     && FAILED(hr = SET_D3D_STATE(effect, SetVertexShader,
1506                     *(IDirect3DVertexShader9 **)param_value)))
1507                 ERR("Could not set vertex shader, hr %#x.\n", hr);
1508             else if (*(IDirect3DVertexShader9 **)param_value)
1509                 hr = d3dx_set_shader_constants(effect, pass, param, TRUE, update_all || param_dirty);
1510             return hr;
1511         case SC_PIXELSHADER:
1512             TRACE("%s, shader %p.\n", state_table[state->operation].name, *(IDirect3DPixelShader9 **)param_value);
1513             if ((update_all || param_dirty)
1514                     && FAILED(hr = SET_D3D_STATE(effect, SetPixelShader,
1515                     *(IDirect3DPixelShader9 **)param_value)))
1516                 ERR("Could not set pixel shader, hr %#x.\n", hr);
1517             else if (*(IDirect3DPixelShader9 **)param_value)
1518                 hr = d3dx_set_shader_constants(effect, pass, param, FALSE, update_all || param_dirty);
1519             return hr;
1520         case SC_TRANSFORM:
1521             TRACE("%s, state %u.\n", state_table[state->operation].name, state->index);
1522             return SET_D3D_STATE(effect, SetTransform, state_table[state->operation].op + state->index,
1523                     (D3DMATRIX *)param_value);
1524         case SC_LIGHTENABLE:
1525             TRACE("%s, index %u, value %u.\n", state_table[state->operation].name, state->index, *(BOOL *)param_value);
1526             return SET_D3D_STATE(effect, LightEnable, state->index, *(BOOL *)param_value);
1527         case SC_LIGHT:
1528         {
1529             TRACE("%s, index %u, op %u.\n", state_table[state->operation].name, state->index,
1530                     state_table[state->operation].op);
1531             d3dx9_set_light_parameter(state_table[state->operation].op,
1532                     &effect->current_light[state->index], param_value);
1533             effect->light_updated |= 1u << state->index;
1534             return D3D_OK;
1535         }
1536         case SC_MATERIAL:
1537         {
1538             TRACE("%s, index %u, op %u.\n", state_table[state->operation].name, state->index,
1539                     state_table[state->operation].op);
1540             d3dx9_set_material_parameter(state_table[state->operation].op,
1541                     &effect->current_material, param_value);
1542             effect->material_updated = TRUE;
1543             return D3D_OK;
1544         }
1545         case SC_NPATCHMODE:
1546             TRACE("%s, nsegments %f.\n", state_table[state->operation].name, *(float *)param_value);
1547             return SET_D3D_STATE(effect, SetNPatchMode, *(float *)param_value);
1548         case SC_SHADERCONST:
1549             TRACE("%s, index %u, op %u.\n", state_table[state->operation].name, state->index,
1550                 state_table[state->operation].op);
1551             return d3dx_set_shader_const_state(effect, state_table[state->operation].op, state->index,
1552                 param, param_value);
1553         default:
1554             FIXME("%s not handled.\n", state_table[state->operation].name);
1555             break;
1556     }
1557     return D3D_OK;
1558 }
1559 
1560 static HRESULT d3dx9_apply_pass_states(struct d3dx_effect *effect, struct d3dx_pass *pass, BOOL update_all)
1561 {
1562     unsigned int i;
1563     HRESULT ret;
1564     HRESULT hr;
1565     ULONG64 new_update_version = next_effect_update_version(effect);
1566 
1567     TRACE("effect %p, pass %p, state_count %u.\n", effect, pass, pass->state_count);
1568 
1569     ret = D3D_OK;
1570     for (i = 0; i < pass->state_count; ++i)
1571     {
1572         if (FAILED(hr = d3dx9_apply_state(effect, pass, &pass->states[i], ~0u, update_all)))
1573         {
1574             WARN("Error applying state, hr %#x.\n", hr);
1575             ret = hr;
1576         }
1577     }
1578 
1579     if (effect->light_updated)
1580     {
1581         for (i = 0; i < ARRAY_SIZE(effect->current_light); ++i)
1582         {
1583             if ((effect->light_updated & (1u << i))
1584                     && FAILED(hr = SET_D3D_STATE(effect, SetLight, i, &effect->current_light[i])))
1585             {
1586                 WARN("Error setting light, hr %#x.\n", hr);
1587                 ret = hr;
1588             }
1589         }
1590         effect->light_updated = 0;
1591     }
1592 
1593     if (effect->material_updated
1594             && FAILED(hr = SET_D3D_STATE(effect, SetMaterial, &effect->current_material)))
1595     {
1596         WARN("Error setting material, hr %#x.\n", hr);
1597         ret = hr;
1598     }
1599     effect->material_updated = FALSE;
1600 
1601     pass->update_version = new_update_version;
1602     return ret;
1603 }
1604 
1605 static void param_set_data_pointer(struct d3dx_parameter *param, unsigned char *data, BOOL child, BOOL free_data)
1606 {
1607     unsigned char *member_data = data;
1608     unsigned int i, count;
1609 
1610     count = param->element_count ? param->element_count : param->member_count;
1611     for (i = 0; i < count; ++i)
1612     {
1613         param_set_data_pointer(&param->members[i], member_data, TRUE, free_data);
1614         if (data)
1615             member_data += param->members[i].bytes;
1616     }
1617     if (free_data)
1618         free_parameter_data(param, child);
1619     param->data = data;
1620 }
1621 
1622 static BOOL is_same_parameter(void *param1_, struct d3dx_parameter *param2)
1623 {
1624     struct d3dx_parameter *param1 = (struct d3dx_parameter *)param1_;
1625     BOOL matches;
1626     unsigned int i, member_count;
1627 
1628     matches = !strcmp(param1->name, param2->name) && param1->class == param2->class
1629             && param1->type == param2->type && param1->rows == param2->rows
1630             && param1->columns == param2->columns && param1->element_count == param2->element_count
1631             && param1->member_count == param2->member_count;
1632 
1633     member_count = param1->element_count ? param1->element_count : param1->member_count;
1634 
1635     if (!matches || !member_count)
1636         return matches;
1637 
1638     for (i = 0; i < member_count; ++i)
1639     {
1640         if (!is_same_parameter(&param1->members[i], &param2->members[i]))
1641             return FALSE;
1642     }
1643     return TRUE;
1644 }
1645 
1646 static HRESULT d3dx_pool_sync_shared_parameter(struct d3dx_effect_pool *pool, struct d3dx_top_level_parameter *param)
1647 {
1648     unsigned int i, free_entry_index;
1649     unsigned int new_size, new_count;
1650 
1651     if (!(param->param.flags & PARAMETER_FLAG_SHARED) || !pool || is_param_type_sampler(param->param.type))
1652         return D3D_OK;
1653 
1654     free_entry_index = pool->size;
1655     for (i = 0; i < pool->size; ++i)
1656     {
1657         if (!pool->shared_data[i].count)
1658             free_entry_index = i;
1659         else if (is_same_parameter(&param->param, &pool->shared_data[i].parameters[0]->param))
1660             break;
1661     }
1662     if (i == pool->size)
1663     {
1664         i = free_entry_index;
1665         if (i == pool->size)
1666         {
1667             struct d3dx_shared_data *new_alloc;
1668 
1669             if (!pool->size)
1670             {
1671                 new_size = INITIAL_POOL_SIZE;
1672                 new_alloc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1673                         sizeof(*pool->shared_data) * new_size);
1674                 if (!new_alloc)
1675                 {
1676                     ERR("Out of memory.\n");
1677                     return E_OUTOFMEMORY;
1678                 }
1679             }
1680             else
1681             {
1682                 new_size = pool->size * 2;
1683                 new_alloc = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pool->shared_data,
1684                         sizeof(*pool->shared_data) * new_size);
1685                 if (!new_alloc)
1686                 {
1687                     ERR("Out of memory.\n");
1688                     return E_OUTOFMEMORY;
1689                 }
1690                 if (new_alloc != pool->shared_data)
1691                 {
1692                     unsigned int j, k;
1693 
1694                     for (j = 0; j < pool->size; ++j)
1695                         for (k = 0; k < new_alloc[j].count; ++k)
1696                             new_alloc[j].parameters[k]->shared_data = &new_alloc[j];
1697                 }
1698             }
1699             pool->shared_data = new_alloc;
1700             pool->size = new_size;
1701         }
1702         pool->shared_data[i].data = param->param.data;
1703     }
1704     else
1705     {
1706         param_set_data_pointer(&param->param, pool->shared_data[i].data, FALSE, TRUE);
1707     }
1708     new_count = ++pool->shared_data[i].count;
1709     if (new_count >= pool->shared_data[i].size)
1710     {
1711         if (!pool->shared_data[i].size)
1712         {
1713             new_size = INITIAL_SHARED_DATA_SIZE;
1714             pool->shared_data[i].parameters = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1715                     sizeof(*pool->shared_data[i].parameters) * INITIAL_SHARED_DATA_SIZE);
1716         }
1717         else
1718         {
1719             new_size = pool->shared_data[i].size * 2;
1720             pool->shared_data[i].parameters = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1721                     pool->shared_data[i].parameters,
1722                     sizeof(*pool->shared_data[i].parameters) * new_size);
1723         }
1724         pool->shared_data[i].size = new_size;
1725     }
1726 
1727     param->shared_data = &pool->shared_data[i];
1728     pool->shared_data[i].parameters[new_count - 1] = param;
1729 
1730     TRACE("name %s, parameter idx %u, new refcount %u.\n", debugstr_a(param->param.name), i,
1731             new_count);
1732 
1733     return D3D_OK;
1734 }
1735 
1736 static BOOL param_zero_data_func(void *dummy, struct d3dx_parameter *param)
1737 {
1738     param->data = NULL;
1739     return FALSE;
1740 }
1741 
1742 static void d3dx_pool_release_shared_parameter(struct d3dx_top_level_parameter *param)
1743 {
1744     unsigned int new_count;
1745 
1746     if (!(param->param.flags & PARAMETER_FLAG_SHARED) || !param->shared_data)
1747         return;
1748     new_count = --param->shared_data->count;
1749 
1750     TRACE("param %p, param->shared_data %p, new_count %d.\n", param, param->shared_data, new_count);
1751 
1752     if (new_count)
1753     {
1754         unsigned int i;
1755 
1756         for (i = 0; i < new_count; ++i)
1757         {
1758             if (param->shared_data->parameters[i] == param)
1759             {
1760                 memmove(&param->shared_data->parameters[i],
1761                         &param->shared_data->parameters[i + 1],
1762                         sizeof(param->shared_data->parameters[i]) * (new_count - i));
1763                 break;
1764             }
1765         }
1766         walk_parameter_tree(&param->param, param_zero_data_func, NULL);
1767     }
1768     else
1769     {
1770         HeapFree(GetProcessHeap(), 0, param->shared_data->parameters);
1771         /* Zeroing table size is required as the entry in pool parameters table can be reused. */
1772         param->shared_data->size = 0;
1773         param->shared_data = NULL;
1774     }
1775 }
1776 
1777 static inline struct d3dx_effect_pool *impl_from_ID3DXEffectPool(ID3DXEffectPool *iface)
1778 {
1779     return CONTAINING_RECORD(iface, struct d3dx_effect_pool, ID3DXEffectPool_iface);
1780 }
1781 
1782 static inline struct d3dx_effect *impl_from_ID3DXEffect(ID3DXEffect *iface)
1783 {
1784     return CONTAINING_RECORD(iface, struct d3dx_effect, ID3DXEffect_iface);
1785 }
1786 
1787 /*** IUnknown methods ***/
1788 static HRESULT WINAPI d3dx_effect_QueryInterface(ID3DXEffect *iface, REFIID riid, void **object)
1789 {
1790     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), object);
1791 
1792     if (IsEqualGUID(riid, &IID_IUnknown) ||
1793         IsEqualGUID(riid, &IID_ID3DXEffect))
1794     {
1795         iface->lpVtbl->AddRef(iface);
1796         *object = iface;
1797         return S_OK;
1798     }
1799 
1800     ERR("Interface %s not found\n", debugstr_guid(riid));
1801 
1802     return E_NOINTERFACE;
1803 }
1804 
1805 static ULONG WINAPI d3dx_effect_AddRef(ID3DXEffect *iface)
1806 {
1807     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
1808 
1809     TRACE("(%p)->(): AddRef from %u\n", This, This->ref);
1810 
1811     return InterlockedIncrement(&This->ref);
1812 }
1813 
1814 static ULONG WINAPI d3dx_effect_Release(ID3DXEffect *iface)
1815 {
1816     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
1817     ULONG refcount = InterlockedDecrement(&effect->ref);
1818 
1819     TRACE("%p decreasing refcount to %u.\n", effect, refcount);
1820 
1821     if (!refcount)
1822         d3dx_effect_cleanup(effect);
1823 
1824     return refcount;
1825 }
1826 
1827 /*** ID3DXBaseEffect methods ***/
1828 static HRESULT WINAPI d3dx_effect_GetDesc(ID3DXEffect *iface, D3DXEFFECT_DESC *desc)
1829 {
1830     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
1831 
1832     FIXME("iface %p, desc %p partial stub.\n", iface, desc);
1833 
1834     if (!desc)
1835     {
1836         WARN("Invalid argument specified.\n");
1837         return D3DERR_INVALIDCALL;
1838     }
1839 
1840     /* TODO: add creator and function count. */
1841     desc->Creator = NULL;
1842     desc->Functions = 0;
1843     desc->Parameters = effect->parameter_count;
1844     desc->Techniques = effect->technique_count;
1845 
1846     return D3D_OK;
1847 }
1848 
1849 static HRESULT WINAPI d3dx_effect_GetParameterDesc(ID3DXEffect *iface, D3DXHANDLE parameter,
1850         D3DXPARAMETER_DESC *desc)
1851 {
1852     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
1853     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
1854 
1855     TRACE("iface %p, parameter %p, desc %p.\n", iface, parameter, desc);
1856 
1857     if (!desc || !param)
1858     {
1859         WARN("Invalid argument specified.\n");
1860         return D3DERR_INVALIDCALL;
1861     }
1862 
1863     desc->Name = param->name;
1864     desc->Semantic = param->semantic;
1865     desc->Class = param->class;
1866     desc->Type = param->type;
1867     desc->Rows = param->rows;
1868     desc->Columns = param->columns;
1869     desc->Elements = param->element_count;
1870     desc->Annotations = is_top_level_parameter(param)
1871             ? top_level_parameter_from_parameter(param)->annotation_count : 0;
1872     desc->StructMembers = param->member_count;
1873     desc->Flags = param->flags;
1874     desc->Bytes = param->bytes;
1875 
1876     return D3D_OK;
1877 }
1878 
1879 static HRESULT WINAPI d3dx_effect_GetTechniqueDesc(ID3DXEffect *iface, D3DXHANDLE technique,
1880         D3DXTECHNIQUE_DESC *desc)
1881 {
1882     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
1883     struct d3dx_technique *tech = technique ? get_valid_technique(effect, technique) : &effect->techniques[0];
1884 
1885     TRACE("iface %p, technique %p, desc %p.\n", iface, technique, desc);
1886 
1887     if (!desc || !tech)
1888     {
1889         WARN("Invalid argument specified.\n");
1890         return D3DERR_INVALIDCALL;
1891     }
1892 
1893     desc->Name = tech->name;
1894     desc->Passes = tech->pass_count;
1895     desc->Annotations = tech->annotation_count;
1896 
1897     return D3D_OK;
1898 }
1899 
1900 static HRESULT WINAPI d3dx_effect_GetPassDesc(ID3DXEffect *iface, D3DXHANDLE pass_handle, D3DXPASS_DESC *desc)
1901 {
1902     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
1903     struct d3dx_pass *pass = get_valid_pass(effect, pass_handle);
1904     unsigned int i;
1905 
1906     TRACE("iface %p, pass %p, desc %p.\n", iface, pass, desc);
1907 
1908     if (!desc || !pass)
1909     {
1910         WARN("Invalid argument specified.\n");
1911         return D3DERR_INVALIDCALL;
1912     }
1913 
1914     desc->Name = pass->name;
1915     desc->Annotations = pass->annotation_count;
1916 
1917     desc->pVertexShaderFunction = NULL;
1918     desc->pPixelShaderFunction = NULL;
1919 
1920     if (effect->flags & D3DXFX_NOT_CLONEABLE)
1921         return D3D_OK;
1922 
1923     for (i = 0; i < pass->state_count; ++i)
1924     {
1925         struct d3dx_state *state = &pass->states[i];
1926 
1927         if (state_table[state->operation].class == SC_VERTEXSHADER
1928                 || state_table[state->operation].class == SC_PIXELSHADER)
1929         {
1930             struct d3dx_parameter *param;
1931             void *param_value;
1932             BOOL param_dirty;
1933             HRESULT hr;
1934             void *data;
1935 
1936             if (FAILED(hr = d3dx9_get_param_value_ptr(pass, &pass->states[i], &param_value, &param,
1937                     FALSE, &param_dirty)))
1938                 return hr;
1939 
1940             data = param->object_id ? effect->objects[param->object_id].data : NULL;
1941             if (state_table[state->operation].class == SC_VERTEXSHADER)
1942                 desc->pVertexShaderFunction = data;
1943             else
1944                 desc->pPixelShaderFunction = data;
1945         }
1946     }
1947 
1948     return D3D_OK;
1949 }
1950 
1951 static HRESULT WINAPI d3dx_effect_GetFunctionDesc(ID3DXEffect *iface, D3DXHANDLE shader,
1952         D3DXFUNCTION_DESC *desc)
1953 {
1954     FIXME("iface %p, shader %p, desc %p stub.\n", iface, shader, desc);
1955 
1956     return E_NOTIMPL;
1957 }
1958 
1959 static D3DXHANDLE WINAPI d3dx_effect_GetParameter(ID3DXEffect *iface, D3DXHANDLE parameter, UINT index)
1960 {
1961     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
1962     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
1963 
1964     TRACE("iface %p, parameter %p, index %u.\n", iface, parameter, index);
1965 
1966     if (!parameter)
1967     {
1968         if (index < effect->parameter_count)
1969         {
1970             TRACE("Returning parameter %p.\n", &effect->parameters[index]);
1971             return get_parameter_handle(&effect->parameters[index].param);
1972         }
1973     }
1974     else
1975     {
1976         if (param && !param->element_count && index < param->member_count)
1977         {
1978             TRACE("Returning parameter %p.\n", &param->members[index]);
1979             return get_parameter_handle(&param->members[index]);
1980         }
1981     }
1982 
1983     WARN("Parameter not found.\n");
1984 
1985     return NULL;
1986 }
1987 
1988 static D3DXHANDLE WINAPI d3dx_effect_GetParameterByName(ID3DXEffect *iface, D3DXHANDLE parameter,
1989         const char *name)
1990 {
1991     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
1992     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
1993     D3DXHANDLE handle;
1994 
1995     TRACE("iface %p, parameter %p, name %s.\n", iface, parameter, debugstr_a(name));
1996 
1997     if (!name)
1998     {
1999         handle = get_parameter_handle(param);
2000         TRACE("Returning parameter %p.\n", handle);
2001         return handle;
2002     }
2003 
2004     handle = get_parameter_handle(get_parameter_by_name(effect, param, name));
2005     TRACE("Returning parameter %p.\n", handle);
2006 
2007     return handle;
2008 }
2009 
2010 static D3DXHANDLE WINAPI d3dx_effect_GetParameterBySemantic(ID3DXEffect *iface, D3DXHANDLE parameter,
2011         const char *semantic)
2012 {
2013     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2014     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2015     struct d3dx_parameter *temp_param;
2016     unsigned int i;
2017 
2018     TRACE("iface %p, parameter %p, semantic %s.\n", iface, parameter, debugstr_a(semantic));
2019 
2020     if (!parameter)
2021     {
2022         for (i = 0; i < effect->parameter_count; ++i)
2023         {
2024             temp_param = &effect->parameters[i].param;
2025 
2026             if (!temp_param->semantic)
2027             {
2028                 if (!semantic)
2029                 {
2030                     TRACE("Returning parameter %p\n", temp_param);
2031                     return get_parameter_handle(temp_param);
2032                 }
2033                 continue;
2034             }
2035 
2036             if (!strcasecmp(temp_param->semantic, semantic))
2037             {
2038                 TRACE("Returning parameter %p\n", temp_param);
2039                 return get_parameter_handle(temp_param);
2040             }
2041         }
2042     }
2043     else if (param)
2044     {
2045         for (i = 0; i < param->member_count; ++i)
2046         {
2047             temp_param = &param->members[i];
2048 
2049             if (!temp_param->semantic)
2050             {
2051                 if (!semantic)
2052                 {
2053                     TRACE("Returning parameter %p\n", temp_param);
2054                     return get_parameter_handle(temp_param);
2055                 }
2056                 continue;
2057             }
2058 
2059             if (!strcasecmp(temp_param->semantic, semantic))
2060             {
2061                 TRACE("Returning parameter %p\n", temp_param);
2062                 return get_parameter_handle(temp_param);
2063             }
2064         }
2065     }
2066 
2067     WARN("Parameter not found.\n");
2068 
2069     return NULL;
2070 }
2071 
2072 static D3DXHANDLE WINAPI d3dx_effect_GetParameterElement(ID3DXEffect *iface, D3DXHANDLE parameter, UINT index)
2073 {
2074     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2075     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2076 
2077     TRACE("iface %p, parameter %p, index %u.\n", iface, parameter, index);
2078 
2079     if (!param)
2080     {
2081         if (index < effect->parameter_count)
2082         {
2083             TRACE("Returning parameter %p.\n", &effect->parameters[index]);
2084             return get_parameter_handle(&effect->parameters[index].param);
2085         }
2086     }
2087     else
2088     {
2089         if (index < param->element_count)
2090         {
2091             TRACE("Returning parameter %p.\n", &param->members[index]);
2092             return get_parameter_handle(&param->members[index]);
2093         }
2094     }
2095 
2096     WARN("Parameter not found.\n");
2097 
2098     return NULL;
2099 }
2100 
2101 static D3DXHANDLE WINAPI d3dx_effect_GetTechnique(ID3DXEffect *iface, UINT index)
2102 {
2103     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2104 
2105     TRACE("iface %p, index %u.\n", iface, index);
2106 
2107     if (index >= effect->technique_count)
2108     {
2109         WARN("Invalid argument specified.\n");
2110         return NULL;
2111     }
2112 
2113     TRACE("Returning technique %p.\n", &effect->techniques[index]);
2114 
2115     return get_technique_handle(&effect->techniques[index]);
2116 }
2117 
2118 static D3DXHANDLE WINAPI d3dx_effect_GetTechniqueByName(ID3DXEffect *iface, const char *name)
2119 {
2120     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2121     struct d3dx_technique *tech = get_technique_by_name(effect, name);
2122 
2123     TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
2124 
2125     if (tech)
2126     {
2127         D3DXHANDLE t = get_technique_handle(tech);
2128         TRACE("Returning technique %p\n", t);
2129         return t;
2130     }
2131 
2132     WARN("Technique not found.\n");
2133 
2134     return NULL;
2135 }
2136 
2137 static D3DXHANDLE WINAPI d3dx_effect_GetPass(ID3DXEffect *iface, D3DXHANDLE technique, UINT index)
2138 {
2139     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2140     struct d3dx_technique *tech = get_valid_technique(effect, technique);
2141 
2142     TRACE("iface %p, technique %p, index %u.\n", iface, technique, index);
2143 
2144     if (tech && index < tech->pass_count)
2145     {
2146         TRACE("Returning pass %p\n", &tech->passes[index]);
2147         return get_pass_handle(&tech->passes[index]);
2148     }
2149 
2150     WARN("Pass not found.\n");
2151 
2152     return NULL;
2153 }
2154 
2155 static D3DXHANDLE WINAPI d3dx_effect_GetPassByName(ID3DXEffect *iface, D3DXHANDLE technique, const char *name)
2156 {
2157     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2158     struct d3dx_technique *tech = get_valid_technique(effect, technique);
2159 
2160     TRACE("iface %p, technique %p, name %s.\n", iface, technique, debugstr_a(name));
2161 
2162     if (tech && name)
2163     {
2164         unsigned int i;
2165 
2166         for (i = 0; i < tech->pass_count; ++i)
2167         {
2168             struct d3dx_pass *pass = &tech->passes[i];
2169 
2170             if (!strcmp(pass->name, name))
2171             {
2172                 TRACE("Returning pass %p\n", pass);
2173                 return get_pass_handle(pass);
2174             }
2175         }
2176     }
2177 
2178     WARN("Pass not found.\n");
2179 
2180     return NULL;
2181 }
2182 
2183 static D3DXHANDLE WINAPI d3dx_effect_GetFunction(ID3DXEffect *iface, UINT index)
2184 {
2185     FIXME("iface %p, index %u stub.\n", iface, index);
2186 
2187     return NULL;
2188 }
2189 
2190 static D3DXHANDLE WINAPI d3dx_effect_GetFunctionByName(ID3DXEffect *iface, const char *name)
2191 {
2192     FIXME("iface %p, name %s stub.\n", iface, debugstr_a(name));
2193 
2194     return NULL;
2195 }
2196 
2197 static D3DXHANDLE WINAPI d3dx_effect_GetAnnotation(ID3DXEffect *iface, D3DXHANDLE object, UINT index)
2198 {
2199     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2200     struct d3dx_parameter *annotations = NULL;
2201     unsigned int annotation_count;
2202 
2203     TRACE("iface %p, object %p, index %u.\n", iface, object, index);
2204 
2205     annotation_count = get_annotation_from_object(effect, object, &annotations);
2206 
2207     if (index < annotation_count)
2208     {
2209         TRACE("Returning parameter %p\n", &annotations[index]);
2210         return get_parameter_handle(&annotations[index]);
2211     }
2212 
2213     WARN("Annotation not found.\n");
2214 
2215     return NULL;
2216 }
2217 
2218 static D3DXHANDLE WINAPI d3dx_effect_GetAnnotationByName(ID3DXEffect *iface, D3DXHANDLE object,
2219         const char *name)
2220 {
2221     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2222     struct d3dx_parameter *annotation = NULL;
2223     struct d3dx_parameter *annotations = NULL;
2224     unsigned int annotation_count;
2225 
2226     TRACE("iface %p, object %p, name %s.\n", iface, object, debugstr_a(name));
2227 
2228     if (!name)
2229     {
2230         WARN("Invalid argument specified\n");
2231         return NULL;
2232     }
2233 
2234     annotation_count = get_annotation_from_object(effect, object, &annotations);
2235 
2236     annotation = get_annotation_by_name(effect, annotation_count, annotations, name);
2237     if (annotation)
2238     {
2239         TRACE("Returning parameter %p\n", annotation);
2240         return get_parameter_handle(annotation);
2241     }
2242 
2243     WARN("Annotation not found.\n");
2244 
2245     return NULL;
2246 }
2247 
2248 static HRESULT WINAPI d3dx_effect_SetValue(ID3DXEffect *iface, D3DXHANDLE parameter,
2249         const void *data, UINT bytes)
2250 {
2251     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2252     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2253     unsigned int i;
2254 
2255     TRACE("iface %p, parameter %p, data %p, bytes %u.\n", iface, parameter, data, bytes);
2256 
2257     if (!param)
2258     {
2259         WARN("Invalid parameter %p specified.\n", parameter);
2260         return D3DERR_INVALIDCALL;
2261     }
2262     if (param->class == D3DXPC_OBJECT && is_param_type_sampler(param->type))
2263     {
2264         WARN("Parameter is a sampler, returning E_FAIL.\n");
2265         return E_FAIL;
2266     }
2267 
2268     if (data && param->bytes <= bytes)
2269     {
2270         switch (param->type)
2271         {
2272             case D3DXPT_TEXTURE:
2273             case D3DXPT_TEXTURE1D:
2274             case D3DXPT_TEXTURE2D:
2275             case D3DXPT_TEXTURE3D:
2276             case D3DXPT_TEXTURECUBE:
2277                 for (i = 0; i < (param->element_count ? param->element_count : 1); ++i)
2278                 {
2279                     IUnknown *old_texture = ((IUnknown **)param->data)[i];
2280                     IUnknown *new_texture = ((IUnknown **)data)[i];
2281 
2282                     if (new_texture == old_texture)
2283                         continue;
2284 
2285                     if (new_texture)
2286                         IUnknown_AddRef(new_texture);
2287                     if (old_texture)
2288                         IUnknown_Release(old_texture);
2289                 }
2290             /* fallthrough */
2291             case D3DXPT_VOID:
2292             case D3DXPT_BOOL:
2293             case D3DXPT_INT:
2294             case D3DXPT_FLOAT:
2295                 TRACE("Copy %u bytes.\n", param->bytes);
2296                 memcpy(param->data, data, param->bytes);
2297                 set_dirty(param);
2298                 break;
2299 
2300             case D3DXPT_STRING:
2301             {
2302                 HRESULT hr;
2303 
2304                 set_dirty(param);
2305                 for (i = 0; i < (param->element_count ? param->element_count : 1); ++i)
2306                     if (FAILED(hr = set_string(&((char **)param->data)[i], ((const char **)data)[i])))
2307                         return hr;
2308                 break;
2309             }
2310 
2311             default:
2312                 FIXME("Unhandled type %s.\n", debug_d3dxparameter_type(param->type));
2313                 break;
2314         }
2315 
2316         return D3D_OK;
2317     }
2318 
2319     WARN("Invalid argument specified.\n");
2320 
2321     return D3DERR_INVALIDCALL;
2322 }
2323 
2324 static HRESULT WINAPI d3dx_effect_GetValue(ID3DXEffect *iface, D3DXHANDLE parameter, void *data, UINT bytes)
2325 {
2326     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2327     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2328 
2329     TRACE("iface %p, parameter %p, data %p, bytes %u.\n", iface, parameter, data, bytes);
2330 
2331     if (!param)
2332     {
2333         WARN("Invalid parameter %p specified.\n", parameter);
2334         return D3DERR_INVALIDCALL;
2335     }
2336     if (param->class == D3DXPC_OBJECT && is_param_type_sampler(param->type))
2337     {
2338         WARN("Parameter is a sampler, returning E_FAIL.\n");
2339         return E_FAIL;
2340     }
2341 
2342     if (data && param->bytes <= bytes)
2343     {
2344         TRACE("Type %s.\n", debug_d3dxparameter_type(param->type));
2345 
2346         switch (param->type)
2347         {
2348             case D3DXPT_VOID:
2349             case D3DXPT_BOOL:
2350             case D3DXPT_INT:
2351             case D3DXPT_FLOAT:
2352             case D3DXPT_STRING:
2353                 break;
2354 
2355             case D3DXPT_VERTEXSHADER:
2356             case D3DXPT_PIXELSHADER:
2357             case D3DXPT_TEXTURE:
2358             case D3DXPT_TEXTURE1D:
2359             case D3DXPT_TEXTURE2D:
2360             case D3DXPT_TEXTURE3D:
2361             case D3DXPT_TEXTURECUBE:
2362             {
2363                 unsigned int i;
2364 
2365                 for (i = 0; i < (param->element_count ? param->element_count : 1); ++i)
2366                 {
2367                     IUnknown *unk = ((IUnknown **)param->data)[i];
2368                     if (unk)
2369                         IUnknown_AddRef(unk);
2370                 }
2371                 break;
2372             }
2373 
2374             default:
2375                 FIXME("Unhandled type %s.\n", debug_d3dxparameter_type(param->type));
2376                 break;
2377         }
2378 
2379         TRACE("Copy %u bytes.\n", param->bytes);
2380         memcpy(data, param->data, param->bytes);
2381         return D3D_OK;
2382     }
2383 
2384     WARN("Parameter not found.\n");
2385 
2386     return D3DERR_INVALIDCALL;
2387 }
2388 
2389 static HRESULT WINAPI d3dx_effect_SetBool(ID3DXEffect *iface, D3DXHANDLE parameter, BOOL b)
2390 {
2391     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2392     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2393 
2394     TRACE("iface %p, parameter %p, b %#x.\n", iface, parameter, b);
2395 
2396     if (param && !param->element_count && param->rows == 1 && param->columns == 1)
2397     {
2398         set_number(param->data, param->type, &b, D3DXPT_BOOL);
2399         set_dirty(param);
2400         return D3D_OK;
2401     }
2402 
2403     WARN("Parameter not found.\n");
2404 
2405     return D3DERR_INVALIDCALL;
2406 }
2407 
2408 static HRESULT WINAPI d3dx_effect_GetBool(ID3DXEffect *iface, D3DXHANDLE parameter, BOOL *b)
2409 {
2410     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2411     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2412 
2413     TRACE("iface %p, parameter %p, b %p.\n", iface, parameter, b);
2414 
2415     if (b && param && !param->element_count && param->rows == 1 && param->columns == 1)
2416     {
2417         set_number(b, D3DXPT_BOOL, param->data, param->type);
2418         TRACE("Returning %s\n", *b ? "TRUE" : "FALSE");
2419         return D3D_OK;
2420     }
2421 
2422     WARN("Parameter not found.\n");
2423 
2424     return D3DERR_INVALIDCALL;
2425 }
2426 
2427 static HRESULT WINAPI d3dx_effect_SetBoolArray(ID3DXEffect *iface, D3DXHANDLE parameter, const BOOL *b, UINT count)
2428 {
2429     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2430     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2431 
2432     TRACE("iface %p, parameter %p, b %p, count %u.\n", iface, parameter, b, count);
2433 
2434     if (param)
2435     {
2436         unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2437 
2438         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2439 
2440         switch (param->class)
2441         {
2442             case D3DXPC_SCALAR:
2443             case D3DXPC_VECTOR:
2444             case D3DXPC_MATRIX_ROWS:
2445                 for (i = 0; i < size; ++i)
2446                 {
2447                     /* don't crop the input, use D3DXPT_INT instead of D3DXPT_BOOL */
2448                     set_number((DWORD *)param->data + i, param->type, &b[i], D3DXPT_INT);
2449                 }
2450                 set_dirty(param);
2451                 return D3D_OK;
2452 
2453             case D3DXPC_OBJECT:
2454             case D3DXPC_STRUCT:
2455                 break;
2456 
2457             default:
2458                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2459                 break;
2460         }
2461     }
2462 
2463     WARN("Parameter not found.\n");
2464 
2465     return D3DERR_INVALIDCALL;
2466 }
2467 
2468 static HRESULT WINAPI d3dx_effect_GetBoolArray(ID3DXEffect *iface, D3DXHANDLE parameter, BOOL *b, UINT count)
2469 {
2470     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2471     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2472 
2473     TRACE("iface %p, parameter %p, b %p, count %u.\n", iface, parameter, b, count);
2474 
2475     if (b && param && (param->class == D3DXPC_SCALAR
2476             || param->class == D3DXPC_VECTOR
2477             || param->class == D3DXPC_MATRIX_ROWS
2478             || param->class == D3DXPC_MATRIX_COLUMNS))
2479     {
2480         unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2481 
2482         for (i = 0; i < size; ++i)
2483         {
2484             set_number(&b[i], D3DXPT_BOOL, (DWORD *)param->data + i, param->type);
2485         }
2486         return D3D_OK;
2487     }
2488 
2489     WARN("Parameter not found.\n");
2490 
2491     return D3DERR_INVALIDCALL;
2492 }
2493 
2494 static HRESULT WINAPI d3dx_effect_SetInt(ID3DXEffect *iface, D3DXHANDLE parameter, INT n)
2495 {
2496     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2497     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2498 
2499     TRACE("iface %p, parameter %p, n %d.\n", iface, parameter, n);
2500 
2501     if (param && !param->element_count)
2502     {
2503         if (param->rows == 1 && param->columns == 1)
2504         {
2505             DWORD value;
2506 
2507             set_number(&value, param->type, &n, D3DXPT_INT);
2508             if (value != *(DWORD *)param->data)
2509                 set_dirty(param);
2510             *(DWORD *)param->data = value;
2511             return D3D_OK;
2512         }
2513 
2514         /* Split the value if parameter is a vector with dimension 3 or 4. */
2515         if (param->type == D3DXPT_FLOAT
2516                 && ((param->class == D3DXPC_VECTOR && param->columns != 2)
2517                 || (param->class == D3DXPC_MATRIX_ROWS && param->rows != 2 && param->columns == 1)))
2518         {
2519             TRACE("Vector fixup.\n");
2520 
2521             *(float *)param->data = ((n & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE;
2522             ((float *)param->data)[1] = ((n & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE;
2523             ((float *)param->data)[2] = (n & 0xff) * INT_FLOAT_MULTI_INVERSE;
2524             if (param->rows * param->columns > 3)
2525                 ((float *)param->data)[3] = ((n & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE;
2526             set_dirty(param);
2527             return D3D_OK;
2528         }
2529     }
2530 
2531     WARN("Parameter not found.\n");
2532 
2533     return D3DERR_INVALIDCALL;
2534 }
2535 
2536 static HRESULT WINAPI d3dx_effect_GetInt(ID3DXEffect *iface, D3DXHANDLE parameter, INT *n)
2537 {
2538     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2539     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2540 
2541     TRACE("iface %p, parameter %p, n %p.\n", iface, parameter, n);
2542 
2543     if (n && param && !param->element_count)
2544     {
2545         if (param->columns == 1 && param->rows == 1)
2546         {
2547             set_number(n, D3DXPT_INT, param->data, param->type);
2548             TRACE("Returning %d.\n", *n);
2549             return D3D_OK;
2550         }
2551 
2552         if (param->type == D3DXPT_FLOAT &&
2553                 ((param->class == D3DXPC_VECTOR && param->columns != 2)
2554                 || (param->class == D3DXPC_MATRIX_ROWS && param->rows != 2 && param->columns == 1)))
2555         {
2556             TRACE("Vector fixup.\n");
2557 
2558             *n = min(max(0.0f, *((float *)param->data + 2)), 1.0f) * INT_FLOAT_MULTI;
2559             *n += ((int)(min(max(0.0f, *((float *)param->data + 1)), 1.0f) * INT_FLOAT_MULTI)) << 8;
2560             *n += ((int)(min(max(0.0f, *((float *)param->data + 0)), 1.0f) * INT_FLOAT_MULTI)) << 16;
2561             if (param->columns * param->rows > 3)
2562                 *n += ((int)(min(max(0.0f, *((float *)param->data + 3)), 1.0f) * INT_FLOAT_MULTI)) << 24;
2563 
2564             TRACE("Returning %d.\n", *n);
2565             return D3D_OK;
2566         }
2567     }
2568 
2569     WARN("Parameter not found.\n");
2570 
2571     return D3DERR_INVALIDCALL;
2572 }
2573 
2574 static HRESULT WINAPI d3dx_effect_SetIntArray(ID3DXEffect *iface, D3DXHANDLE parameter, const INT *n, UINT count)
2575 {
2576     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2577     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2578 
2579     TRACE("iface %p, parameter %p, n %p, count %u.\n", iface, parameter, n, count);
2580 
2581     if (param)
2582     {
2583         unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2584 
2585         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2586 
2587         switch (param->class)
2588         {
2589             case D3DXPC_SCALAR:
2590             case D3DXPC_VECTOR:
2591             case D3DXPC_MATRIX_ROWS:
2592                 for (i = 0; i < size; ++i)
2593                     set_number((DWORD *)param->data + i, param->type, &n[i], D3DXPT_INT);
2594                 set_dirty(param);
2595                 return D3D_OK;
2596 
2597             case D3DXPC_OBJECT:
2598             case D3DXPC_STRUCT:
2599                 break;
2600 
2601             default:
2602                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2603                 break;
2604         }
2605     }
2606 
2607     WARN("Parameter not found.\n");
2608 
2609     return D3DERR_INVALIDCALL;
2610 }
2611 
2612 static HRESULT WINAPI d3dx_effect_GetIntArray(ID3DXEffect *iface, D3DXHANDLE parameter, INT *n, UINT count)
2613 {
2614     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2615     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2616 
2617     TRACE("iface %p, parameter %p, n %p, count %u.\n", iface, parameter, n, count);
2618 
2619     if (n && param && (param->class == D3DXPC_SCALAR
2620             || param->class == D3DXPC_VECTOR
2621             || param->class == D3DXPC_MATRIX_ROWS
2622             || param->class == D3DXPC_MATRIX_COLUMNS))
2623     {
2624         unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2625 
2626         for (i = 0; i < size; ++i)
2627             set_number(&n[i], D3DXPT_INT, (DWORD *)param->data + i, param->type);
2628         return D3D_OK;
2629     }
2630 
2631     WARN("Parameter not found.\n");
2632 
2633     return D3DERR_INVALIDCALL;
2634 }
2635 
2636 static HRESULT WINAPI d3dx_effect_SetFloat(ID3DXEffect *iface, D3DXHANDLE parameter, float f)
2637 {
2638     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2639     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2640 
2641     TRACE("iface %p, parameter %p, f %.8e.\n", iface, parameter, f);
2642 
2643     if (param && !param->element_count && param->rows == 1 && param->columns == 1)
2644     {
2645         DWORD value;
2646 
2647         set_number(&value, param->type, &f, D3DXPT_FLOAT);
2648         if (value != *(DWORD *)param->data)
2649             set_dirty(param);
2650         *(DWORD *)param->data = value;
2651         return D3D_OK;
2652     }
2653 
2654     WARN("Parameter not found.\n");
2655 
2656     return D3DERR_INVALIDCALL;
2657 }
2658 
2659 static HRESULT WINAPI d3dx_effect_GetFloat(ID3DXEffect *iface, D3DXHANDLE parameter, float *f)
2660 {
2661     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2662     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2663 
2664     TRACE("iface %p, parameter %p, f %p.\n", iface, parameter, f);
2665 
2666     if (f && param && !param->element_count && param->columns == 1 && param->rows == 1)
2667     {
2668         set_number(f, D3DXPT_FLOAT, (DWORD *)param->data, param->type);
2669         TRACE("Returning %f.\n", *f);
2670         return D3D_OK;
2671     }
2672 
2673     WARN("Parameter not found.\n");
2674 
2675     return D3DERR_INVALIDCALL;
2676 }
2677 
2678 static HRESULT WINAPI d3dx_effect_SetFloatArray(ID3DXEffect *iface, D3DXHANDLE parameter,
2679         const float *f, UINT count)
2680 {
2681     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2682     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2683 
2684     TRACE("iface %p, parameter %p, f %p, count %u.\n", iface, parameter, f, count);
2685 
2686     if (param)
2687     {
2688         unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2689 
2690         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2691 
2692         switch (param->class)
2693         {
2694             case D3DXPC_SCALAR:
2695             case D3DXPC_VECTOR:
2696             case D3DXPC_MATRIX_ROWS:
2697                 for (i = 0; i < size; ++i)
2698                     set_number((DWORD *)param->data + i, param->type, &f[i], D3DXPT_FLOAT);
2699                 set_dirty(param);
2700                 return D3D_OK;
2701 
2702             case D3DXPC_OBJECT:
2703             case D3DXPC_STRUCT:
2704                 break;
2705 
2706             default:
2707                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2708                 break;
2709         }
2710     }
2711 
2712     WARN("Parameter not found.\n");
2713 
2714     return D3DERR_INVALIDCALL;
2715 }
2716 
2717 static HRESULT WINAPI d3dx_effect_GetFloatArray(ID3DXEffect *iface, D3DXHANDLE parameter, float *f, UINT count)
2718 {
2719     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2720     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2721 
2722     TRACE("iface %p, parameter %p, f %p, count %u.\n", iface, parameter, f, count);
2723 
2724     if (f && param && (param->class == D3DXPC_SCALAR
2725             || param->class == D3DXPC_VECTOR
2726             || param->class == D3DXPC_MATRIX_ROWS
2727             || param->class == D3DXPC_MATRIX_COLUMNS))
2728     {
2729         unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2730 
2731         for (i = 0; i < size; ++i)
2732             set_number(&f[i], D3DXPT_FLOAT, (DWORD *)param->data + i, param->type);
2733         return D3D_OK;
2734     }
2735 
2736     WARN("Parameter not found.\n");
2737 
2738     return D3DERR_INVALIDCALL;
2739 }
2740 
2741 static HRESULT WINAPI d3dx_effect_SetVector(ID3DXEffect *iface, D3DXHANDLE parameter, const D3DXVECTOR4 *vector)
2742 {
2743     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2744     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2745 
2746     TRACE("iface %p, parameter %p, vector %p.\n", iface, parameter, vector);
2747 
2748     if (param && !param->element_count)
2749     {
2750         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2751 
2752         switch (param->class)
2753         {
2754             case D3DXPC_SCALAR:
2755             case D3DXPC_VECTOR:
2756                 set_dirty(param);
2757                 if (param->type == D3DXPT_INT && param->bytes == 4)
2758                 {
2759                     DWORD tmp;
2760 
2761                     TRACE("INT fixup.\n");
2762                     tmp = max(min(vector->z, 1.0f), 0.0f) * INT_FLOAT_MULTI;
2763                     tmp += ((DWORD)(max(min(vector->y, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 8;
2764                     tmp += ((DWORD)(max(min(vector->x, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 16;
2765                     tmp += ((DWORD)(max(min(vector->w, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 24;
2766 
2767                     *(int *)param->data = tmp;
2768                     return D3D_OK;
2769                 }
2770                 if (param->type == D3DXPT_FLOAT)
2771                 {
2772                     memcpy(param->data, vector, param->columns * sizeof(float));
2773                     return D3D_OK;
2774                 }
2775 
2776                 set_vector(param, vector);
2777                 return D3D_OK;
2778 
2779             case D3DXPC_MATRIX_ROWS:
2780             case D3DXPC_OBJECT:
2781             case D3DXPC_STRUCT:
2782                 break;
2783 
2784             default:
2785                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2786                 break;
2787         }
2788     }
2789 
2790     WARN("Parameter not found.\n");
2791 
2792     return D3DERR_INVALIDCALL;
2793 }
2794 
2795 static HRESULT WINAPI d3dx_effect_GetVector(ID3DXEffect *iface, D3DXHANDLE parameter, D3DXVECTOR4 *vector)
2796 {
2797     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2798     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2799 
2800     TRACE("iface %p, parameter %p, vector %p.\n", iface, parameter, vector);
2801 
2802     if (vector && param && !param->element_count)
2803     {
2804         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2805 
2806         switch (param->class)
2807         {
2808             case D3DXPC_SCALAR:
2809             case D3DXPC_VECTOR:
2810                 if (param->type == D3DXPT_INT && param->bytes == 4)
2811                 {
2812                     TRACE("INT fixup.\n");
2813                     vector->x = (((*(int *)param->data) & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE;
2814                     vector->y = (((*(int *)param->data) & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE;
2815                     vector->z = ((*(int *)param->data) & 0xff) * INT_FLOAT_MULTI_INVERSE;
2816                     vector->w = (((*(int *)param->data) & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE;
2817                     return D3D_OK;
2818                 }
2819                 get_vector(param, vector);
2820                 return D3D_OK;
2821 
2822             case D3DXPC_MATRIX_ROWS:
2823             case D3DXPC_OBJECT:
2824             case D3DXPC_STRUCT:
2825                 break;
2826 
2827             default:
2828                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2829                 break;
2830         }
2831     }
2832 
2833     WARN("Parameter not found.\n");
2834 
2835     return D3DERR_INVALIDCALL;
2836 }
2837 
2838 static HRESULT WINAPI d3dx_effect_SetVectorArray(ID3DXEffect *iface, D3DXHANDLE parameter,
2839         const D3DXVECTOR4 *vector, UINT count)
2840 {
2841     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2842     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2843 
2844     TRACE("iface %p, parameter %p, vector %p, count %u.\n", iface, parameter, vector, count);
2845 
2846     if (param && param->element_count && param->element_count >= count)
2847     {
2848         unsigned int i;
2849 
2850         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2851 
2852         switch (param->class)
2853         {
2854             case D3DXPC_VECTOR:
2855                 set_dirty(param);
2856                 if (param->type == D3DXPT_FLOAT)
2857                 {
2858                     if (param->columns == 4)
2859                         memcpy(param->data, vector, count * 4 * sizeof(float));
2860                     else
2861                         for (i = 0; i < count; ++i)
2862                             memcpy((float *)param->data + param->columns * i, vector + i,
2863                                     param->columns * sizeof(float));
2864                     return D3D_OK;
2865                 }
2866 
2867                 for (i = 0; i < count; ++i)
2868                     set_vector(&param->members[i], &vector[i]);
2869                 return D3D_OK;
2870 
2871             case D3DXPC_SCALAR:
2872             case D3DXPC_MATRIX_ROWS:
2873             case D3DXPC_OBJECT:
2874             case D3DXPC_STRUCT:
2875                 break;
2876 
2877             default:
2878                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2879                 break;
2880         }
2881     }
2882 
2883     WARN("Parameter not found.\n");
2884 
2885     return D3DERR_INVALIDCALL;
2886 }
2887 
2888 static HRESULT WINAPI d3dx_effect_GetVectorArray(ID3DXEffect *iface, D3DXHANDLE parameter,
2889         D3DXVECTOR4 *vector, UINT count)
2890 {
2891     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2892     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2893 
2894     TRACE("iface %p, parameter %p, vector %p, count %u.\n", iface, parameter, vector, count);
2895 
2896     if (!count)
2897         return D3D_OK;
2898 
2899     if (vector && param && count <= param->element_count)
2900     {
2901         unsigned int i;
2902 
2903         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2904 
2905         switch (param->class)
2906         {
2907             case D3DXPC_VECTOR:
2908                 for (i = 0; i < count; ++i)
2909                     get_vector(&param->members[i], &vector[i]);
2910                 return D3D_OK;
2911 
2912             case D3DXPC_SCALAR:
2913             case D3DXPC_MATRIX_ROWS:
2914             case D3DXPC_OBJECT:
2915             case D3DXPC_STRUCT:
2916                 break;
2917 
2918             default:
2919                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2920                 break;
2921         }
2922     }
2923 
2924     WARN("Parameter not found.\n");
2925 
2926     return D3DERR_INVALIDCALL;
2927 }
2928 
2929 static HRESULT WINAPI d3dx_effect_SetMatrix(ID3DXEffect *iface, D3DXHANDLE parameter, const D3DXMATRIX *matrix)
2930 {
2931     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2932     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2933 
2934     TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
2935 
2936     if (param && !param->element_count)
2937     {
2938         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2939 
2940         switch (param->class)
2941         {
2942             case D3DXPC_MATRIX_ROWS:
2943                 set_matrix(param, matrix);
2944                 set_dirty(param);
2945                 return D3D_OK;
2946 
2947             case D3DXPC_SCALAR:
2948             case D3DXPC_VECTOR:
2949             case D3DXPC_OBJECT:
2950             case D3DXPC_STRUCT:
2951                 break;
2952 
2953             default:
2954                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2955                 break;
2956         }
2957     }
2958 
2959     WARN("Parameter not found.\n");
2960 
2961     return D3DERR_INVALIDCALL;
2962 }
2963 
2964 static HRESULT WINAPI d3dx_effect_GetMatrix(ID3DXEffect *iface, D3DXHANDLE parameter, D3DXMATRIX *matrix)
2965 {
2966     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2967     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2968 
2969     TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
2970 
2971     if (matrix && param && !param->element_count)
2972     {
2973         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2974 
2975         switch (param->class)
2976         {
2977             case D3DXPC_MATRIX_ROWS:
2978                 get_matrix(param, matrix, FALSE);
2979                 return D3D_OK;
2980 
2981             case D3DXPC_SCALAR:
2982             case D3DXPC_VECTOR:
2983             case D3DXPC_OBJECT:
2984             case D3DXPC_STRUCT:
2985                 break;
2986 
2987             default:
2988                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2989                 break;
2990         }
2991     }
2992 
2993     WARN("Parameter not found.\n");
2994 
2995     return D3DERR_INVALIDCALL;
2996 }
2997 
2998 static HRESULT WINAPI d3dx_effect_SetMatrixArray(ID3DXEffect *iface, D3DXHANDLE parameter,
2999         const D3DXMATRIX *matrix, UINT count)
3000 {
3001     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3002     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3003 
3004     TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3005 
3006     if (param && param->element_count >= count)
3007     {
3008         unsigned int i;
3009 
3010         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3011 
3012         switch (param->class)
3013         {
3014             case D3DXPC_MATRIX_ROWS:
3015                 set_dirty(param);
3016                 for (i = 0; i < count; ++i)
3017                     set_matrix(&param->members[i], &matrix[i]);
3018                 return D3D_OK;
3019 
3020             case D3DXPC_SCALAR:
3021             case D3DXPC_VECTOR:
3022             case D3DXPC_OBJECT:
3023             case D3DXPC_STRUCT:
3024                 break;
3025 
3026             default:
3027                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3028                 break;
3029         }
3030     }
3031 
3032     WARN("Parameter not found.\n");
3033 
3034     return D3DERR_INVALIDCALL;
3035 }
3036 
3037 static HRESULT WINAPI d3dx_effect_GetMatrixArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3038         D3DXMATRIX *matrix, UINT count)
3039 {
3040     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3041     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3042 
3043     TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3044 
3045     if (!count)
3046         return D3D_OK;
3047 
3048     if (matrix && param && count <= param->element_count)
3049     {
3050         unsigned int i;
3051 
3052         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3053 
3054         switch (param->class)
3055         {
3056             case D3DXPC_MATRIX_ROWS:
3057                 for (i = 0; i < count; ++i)
3058                     get_matrix(&param->members[i], &matrix[i], FALSE);
3059                 return D3D_OK;
3060 
3061             case D3DXPC_SCALAR:
3062             case D3DXPC_VECTOR:
3063             case D3DXPC_OBJECT:
3064             case D3DXPC_STRUCT:
3065                 break;
3066 
3067             default:
3068                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3069                 break;
3070         }
3071     }
3072 
3073     WARN("Parameter not found.\n");
3074 
3075     return D3DERR_INVALIDCALL;
3076 }
3077 
3078 static HRESULT WINAPI d3dx_effect_SetMatrixPointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3079         const D3DXMATRIX **matrix, UINT count)
3080 {
3081     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3082     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3083 
3084     TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3085 
3086     if (param && count <= param->element_count)
3087     {
3088         unsigned int i;
3089 
3090         switch (param->class)
3091         {
3092             case D3DXPC_MATRIX_ROWS:
3093                 set_dirty(param);
3094                 for (i = 0; i < count; ++i)
3095                     set_matrix(&param->members[i], matrix[i]);
3096                 return D3D_OK;
3097 
3098             case D3DXPC_SCALAR:
3099             case D3DXPC_VECTOR:
3100             case D3DXPC_OBJECT:
3101                 break;
3102 
3103             default:
3104                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3105                 break;
3106         }
3107     }
3108 
3109     WARN("Parameter not found.\n");
3110 
3111     return D3DERR_INVALIDCALL;
3112 }
3113 
3114 static HRESULT WINAPI d3dx_effect_GetMatrixPointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3115         D3DXMATRIX **matrix, UINT count)
3116 {
3117     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3118     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3119 
3120     TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3121 
3122     if (!count)
3123         return D3D_OK;
3124 
3125     if (param && matrix && count <= param->element_count)
3126     {
3127         unsigned int i;
3128 
3129         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3130 
3131         switch (param->class)
3132         {
3133             case D3DXPC_MATRIX_ROWS:
3134                 for (i = 0; i < count; ++i)
3135                     get_matrix(&param->members[i], matrix[i], FALSE);
3136                 return D3D_OK;
3137 
3138             case D3DXPC_SCALAR:
3139             case D3DXPC_VECTOR:
3140             case D3DXPC_OBJECT:
3141                 break;
3142 
3143             default:
3144                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3145                 break;
3146         }
3147     }
3148 
3149     WARN("Parameter not found.\n");
3150 
3151     return D3DERR_INVALIDCALL;
3152 }
3153 
3154 static HRESULT WINAPI d3dx_effect_SetMatrixTranspose(ID3DXEffect *iface, D3DXHANDLE parameter,
3155         const D3DXMATRIX *matrix)
3156 {
3157     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3158     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3159 
3160     TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3161 
3162     if (param && !param->element_count)
3163     {
3164         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3165 
3166         switch (param->class)
3167         {
3168             case D3DXPC_MATRIX_ROWS:
3169                 set_dirty(param);
3170                 set_matrix_transpose(param, matrix);
3171                 return D3D_OK;
3172 
3173             case D3DXPC_SCALAR:
3174             case D3DXPC_VECTOR:
3175             case D3DXPC_OBJECT:
3176             case D3DXPC_STRUCT:
3177                 break;
3178 
3179             default:
3180                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3181                 break;
3182         }
3183     }
3184 
3185     WARN("Parameter not found.\n");
3186 
3187     return D3DERR_INVALIDCALL;
3188 }
3189 
3190 static HRESULT WINAPI d3dx_effect_GetMatrixTranspose(ID3DXEffect *iface, D3DXHANDLE parameter,
3191         D3DXMATRIX *matrix)
3192 {
3193     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3194     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3195 
3196     TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3197 
3198     if (matrix && param && !param->element_count)
3199     {
3200         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3201 
3202         switch (param->class)
3203         {
3204             case D3DXPC_SCALAR:
3205             case D3DXPC_VECTOR:
3206                 get_matrix(param, matrix, FALSE);
3207                 return D3D_OK;
3208 
3209             case D3DXPC_MATRIX_ROWS:
3210                 get_matrix(param, matrix, TRUE);
3211                 return D3D_OK;
3212 
3213             case D3DXPC_OBJECT:
3214             case D3DXPC_STRUCT:
3215                 break;
3216 
3217             default:
3218                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3219                 break;
3220         }
3221     }
3222 
3223     WARN("Parameter not found.\n");
3224 
3225     return D3DERR_INVALIDCALL;
3226 }
3227 
3228 static HRESULT WINAPI d3dx_effect_SetMatrixTransposeArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3229         const D3DXMATRIX *matrix, UINT count)
3230 {
3231     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3232     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3233 
3234     TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3235 
3236     if (param && param->element_count >= count)
3237     {
3238         unsigned int i;
3239 
3240         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3241 
3242         switch (param->class)
3243         {
3244             case D3DXPC_MATRIX_ROWS:
3245                 set_dirty(param);
3246                 for (i = 0; i < count; ++i)
3247                     set_matrix_transpose(&param->members[i], &matrix[i]);
3248                 return D3D_OK;
3249 
3250             case D3DXPC_SCALAR:
3251             case D3DXPC_VECTOR:
3252             case D3DXPC_OBJECT:
3253             case D3DXPC_STRUCT:
3254                 break;
3255 
3256             default:
3257                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3258                 break;
3259         }
3260     }
3261 
3262     WARN("Parameter not found.\n");
3263 
3264     return D3DERR_INVALIDCALL;
3265 }
3266 
3267 static HRESULT WINAPI d3dx_effect_GetMatrixTransposeArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3268         D3DXMATRIX *matrix, UINT count)
3269 {
3270     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3271     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3272 
3273     TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3274 
3275     if (!count)
3276         return D3D_OK;
3277 
3278     if (matrix && param && count <= param->element_count)
3279     {
3280         unsigned int i;
3281 
3282         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3283 
3284         switch (param->class)
3285         {
3286             case D3DXPC_MATRIX_ROWS:
3287                 for (i = 0; i < count; ++i)
3288                     get_matrix(&param->members[i], &matrix[i], TRUE);
3289                 return D3D_OK;
3290 
3291             case D3DXPC_SCALAR:
3292             case D3DXPC_VECTOR:
3293             case D3DXPC_OBJECT:
3294             case D3DXPC_STRUCT:
3295                 break;
3296 
3297             default:
3298                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3299                 break;
3300         }
3301     }
3302 
3303     WARN("Parameter not found.\n");
3304 
3305     return D3DERR_INVALIDCALL;
3306 }
3307 
3308 static HRESULT WINAPI d3dx_effect_SetMatrixTransposePointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3309         const D3DXMATRIX **matrix, UINT count)
3310 {
3311     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3312     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3313 
3314     TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3315 
3316     if (param && count <= param->element_count)
3317     {
3318         unsigned int i;
3319 
3320         switch (param->class)
3321         {
3322             case D3DXPC_MATRIX_ROWS:
3323                 set_dirty(param);
3324                 for (i = 0; i < count; ++i)
3325                     set_matrix_transpose(&param->members[i], matrix[i]);
3326                 return D3D_OK;
3327 
3328             case D3DXPC_SCALAR:
3329             case D3DXPC_VECTOR:
3330             case D3DXPC_OBJECT:
3331                 break;
3332 
3333             default:
3334                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3335                 break;
3336         }
3337     }
3338 
3339     WARN("Parameter not found.\n");
3340 
3341     return D3DERR_INVALIDCALL;
3342 }
3343 
3344 static HRESULT WINAPI d3dx_effect_GetMatrixTransposePointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3345         D3DXMATRIX **matrix, UINT count)
3346 {
3347     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3348     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3349 
3350     TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3351 
3352     if (!count)
3353         return D3D_OK;
3354 
3355     if (matrix && param && count <= param->element_count)
3356     {
3357         unsigned int i;
3358 
3359         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3360 
3361         switch (param->class)
3362         {
3363             case D3DXPC_MATRIX_ROWS:
3364                 for (i = 0; i < count; ++i)
3365                     get_matrix(&param->members[i], matrix[i], TRUE);
3366                 return D3D_OK;
3367 
3368             case D3DXPC_SCALAR:
3369             case D3DXPC_VECTOR:
3370             case D3DXPC_OBJECT:
3371                 break;
3372 
3373             default:
3374                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3375                 break;
3376         }
3377     }
3378 
3379     WARN("Parameter not found.\n");
3380 
3381     return D3DERR_INVALIDCALL;
3382 }
3383 
3384 static HRESULT WINAPI d3dx_effect_SetString(ID3DXEffect *iface, D3DXHANDLE parameter, const char *string)
3385 {
3386     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3387     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3388 
3389     TRACE("iface %p, parameter %p, string %s.\n", iface, parameter, debugstr_a(string));
3390 
3391     if (param && param->type == D3DXPT_STRING)
3392     {
3393         set_dirty(param);
3394         return set_string(param->data, string);
3395     }
3396 
3397     WARN("Parameter not found.\n");
3398 
3399     return D3DERR_INVALIDCALL;
3400 }
3401 
3402 static HRESULT WINAPI d3dx_effect_GetString(ID3DXEffect *iface, D3DXHANDLE parameter, const char **string)
3403 {
3404     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3405     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3406 
3407     TRACE("iface %p, parameter %p, string %p.\n", iface, parameter, string);
3408 
3409     if (string && param && !param->element_count && param->type == D3DXPT_STRING)
3410     {
3411         *string = *(const char **)param->data;
3412         TRACE("Returning %s.\n", debugstr_a(*string));
3413         return D3D_OK;
3414     }
3415 
3416     WARN("Parameter not found.\n");
3417 
3418     return D3DERR_INVALIDCALL;
3419 }
3420 
3421 static HRESULT WINAPI d3dx_effect_SetTexture(ID3DXEffect *iface, D3DXHANDLE parameter,
3422         IDirect3DBaseTexture9 *texture)
3423 {
3424     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3425     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3426 
3427     TRACE("iface %p, parameter %p, texture %p.\n", iface, parameter, texture);
3428 
3429     if (param && !param->element_count
3430             && (param->type == D3DXPT_TEXTURE || param->type == D3DXPT_TEXTURE1D
3431             || param->type == D3DXPT_TEXTURE2D || param->type ==  D3DXPT_TEXTURE3D
3432             || param->type == D3DXPT_TEXTURECUBE))
3433     {
3434         IDirect3DBaseTexture9 *old_texture = *(IDirect3DBaseTexture9 **)param->data;
3435 
3436         if (texture == old_texture)
3437             return D3D_OK;
3438 
3439         if (texture)
3440             IDirect3DBaseTexture9_AddRef(texture);
3441         if (old_texture)
3442             IDirect3DBaseTexture9_Release(old_texture);
3443 
3444         *(IDirect3DBaseTexture9 **)param->data = texture;
3445         set_dirty(param);
3446 
3447         return D3D_OK;
3448     }
3449 
3450     WARN("Parameter not found.\n");
3451 
3452     return D3DERR_INVALIDCALL;
3453 }
3454 
3455 static HRESULT WINAPI d3dx_effect_GetTexture(ID3DXEffect *iface, D3DXHANDLE parameter,
3456         IDirect3DBaseTexture9 **texture)
3457 {
3458     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3459     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3460 
3461     TRACE("iface %p, parameter %p, texture %p.\n", iface, parameter, texture);
3462 
3463     if (texture && param && !param->element_count
3464             && (param->type == D3DXPT_TEXTURE || param->type == D3DXPT_TEXTURE1D
3465             || param->type == D3DXPT_TEXTURE2D || param->type ==  D3DXPT_TEXTURE3D
3466             || param->type == D3DXPT_TEXTURECUBE))
3467     {
3468         *texture = *(IDirect3DBaseTexture9 **)param->data;
3469         if (*texture)
3470             IDirect3DBaseTexture9_AddRef(*texture);
3471         TRACE("Returning %p.\n", *texture);
3472         return D3D_OK;
3473     }
3474 
3475     WARN("Parameter not found.\n");
3476 
3477     return D3DERR_INVALIDCALL;
3478 }
3479 
3480 static HRESULT WINAPI d3dx_effect_GetPixelShader(ID3DXEffect *iface, D3DXHANDLE parameter,
3481         IDirect3DPixelShader9 **shader)
3482 {
3483     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3484     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3485 
3486     TRACE("iface %p, parameter %p, shader %p.\n", iface, parameter, shader);
3487 
3488     if (shader && param && !param->element_count && param->type == D3DXPT_PIXELSHADER)
3489     {
3490         if ((*shader = *(IDirect3DPixelShader9 **)param->data))
3491             IDirect3DPixelShader9_AddRef(*shader);
3492         TRACE("Returning %p.\n", *shader);
3493         return D3D_OK;
3494     }
3495 
3496     WARN("Parameter not found.\n");
3497 
3498     return D3DERR_INVALIDCALL;
3499 }
3500 
3501 static HRESULT WINAPI d3dx_effect_GetVertexShader(ID3DXEffect *iface, D3DXHANDLE parameter,
3502         IDirect3DVertexShader9 **shader)
3503 {
3504     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3505     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3506 
3507     TRACE("iface %p, parameter %p, shader %p.\n", iface, parameter, shader);
3508 
3509     if (shader && param && !param->element_count && param->type == D3DXPT_VERTEXSHADER)
3510     {
3511         if ((*shader = *(IDirect3DVertexShader9 **)param->data))
3512             IDirect3DVertexShader9_AddRef(*shader);
3513         TRACE("Returning %p.\n", *shader);
3514         return D3D_OK;
3515     }
3516 
3517     WARN("Parameter not found.\n");
3518 
3519     return D3DERR_INVALIDCALL;
3520 }
3521 
3522 static HRESULT WINAPI d3dx_effect_SetArrayRange(ID3DXEffect *iface, D3DXHANDLE parameter, UINT start, UINT end)
3523 {
3524     FIXME("iface %p, parameter %p, start %u, end %u stub.\n", iface, parameter, start, end);
3525 
3526     return E_NOTIMPL;
3527 }
3528 
3529 /*** ID3DXEffect methods ***/
3530 static HRESULT WINAPI d3dx_effect_GetPool(ID3DXEffect *iface, ID3DXEffectPool **pool)
3531 {
3532     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3533 
3534     TRACE("iface %p, pool %p.\n", effect, pool);
3535 
3536     if (!pool)
3537     {
3538         WARN("Invalid argument supplied.\n");
3539         return D3DERR_INVALIDCALL;
3540     }
3541 
3542     *pool = NULL;
3543     if (effect->pool)
3544     {
3545         *pool = &effect->pool->ID3DXEffectPool_iface;
3546         (*pool)->lpVtbl->AddRef(*pool);
3547     }
3548 
3549     TRACE("Returning pool %p.\n", *pool);
3550 
3551     return S_OK;
3552 }
3553 
3554 static HRESULT WINAPI d3dx_effect_SetTechnique(ID3DXEffect *iface, D3DXHANDLE technique)
3555 {
3556     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3557     struct d3dx_technique *tech = get_valid_technique(effect, technique);
3558 
3559     TRACE("iface %p, technique %p\n", iface, technique);
3560 
3561     if (tech)
3562     {
3563         effect->active_technique = tech;
3564         TRACE("Technique %p\n", tech);
3565         return D3D_OK;
3566     }
3567 
3568     WARN("Technique not found.\n");
3569 
3570     return D3DERR_INVALIDCALL;
3571 }
3572 
3573 static D3DXHANDLE WINAPI d3dx_effect_GetCurrentTechnique(ID3DXEffect *iface)
3574 {
3575     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
3576 
3577     TRACE("iface %p\n", This);
3578 
3579     return get_technique_handle(This->active_technique);
3580 }
3581 
3582 static HRESULT WINAPI d3dx_effect_ValidateTechnique(ID3DXEffect *iface, D3DXHANDLE technique)
3583 {
3584     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3585     struct d3dx_technique *tech = get_valid_technique(effect, technique);
3586     HRESULT ret = D3D_OK;
3587     unsigned int i, j;
3588 
3589     FIXME("iface %p, technique %p semi-stub.\n", iface, technique);
3590 
3591     if (!tech)
3592     {
3593         ret = D3DERR_INVALIDCALL;
3594         goto done;
3595     }
3596     for (i = 0; i < tech->pass_count; ++i)
3597     {
3598         struct d3dx_pass *pass = &tech->passes[i];
3599 
3600         for (j = 0; j < pass->state_count; ++j)
3601         {
3602             struct d3dx_state *state = &pass->states[j];
3603 
3604             if (state_table[state->operation].class == SC_VERTEXSHADER
3605                     || state_table[state->operation].class == SC_PIXELSHADER)
3606             {
3607                 struct d3dx_parameter *param;
3608                 void *param_value;
3609                 BOOL param_dirty;
3610                 HRESULT hr;
3611 
3612                 if (FAILED(hr = d3dx9_get_param_value_ptr(pass, &pass->states[j], &param_value, &param,
3613                         FALSE, &param_dirty)))
3614                     return hr;
3615 
3616                 if (param->object_id && effect->objects[param->object_id].creation_failed)
3617                 {
3618                     ret = E_FAIL;
3619                     goto done;
3620                 }
3621             }
3622         }
3623     }
3624 done:
3625     TRACE("Returning %#x.\n", ret);
3626     return ret;
3627 }
3628 
3629 static HRESULT WINAPI d3dx_effect_FindNextValidTechnique(ID3DXEffect *iface, D3DXHANDLE technique,
3630         D3DXHANDLE *next_technique)
3631 {
3632     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3633     struct d3dx_technique *prev_tech, *tech;
3634     unsigned int i;
3635 
3636     TRACE("iface %p, technique %p, next_technique %p.\n", iface, technique, next_technique);
3637 
3638     if (technique)
3639     {
3640         if (!(prev_tech = get_valid_technique(effect, technique)))
3641             return D3DERR_INVALIDCALL;
3642 
3643         for (i = 0; i < effect->technique_count; ++i)
3644         {
3645             tech = &effect->techniques[i];
3646             if (tech == prev_tech)
3647             {
3648                 ++i;
3649                 break;
3650             }
3651         }
3652     }
3653     else
3654     {
3655         i = 0;
3656     }
3657 
3658     for (; i < effect->technique_count; ++i)
3659     {
3660         tech = &effect->techniques[i];
3661         if (SUCCEEDED(d3dx_effect_ValidateTechnique(iface, get_technique_handle(tech))))
3662         {
3663             *next_technique = get_technique_handle(tech);
3664             return D3D_OK;
3665         }
3666     }
3667 
3668     *next_technique = get_technique_handle(&effect->techniques[0]);
3669     return S_FALSE;
3670 }
3671 
3672 static BOOL walk_parameter_dep(struct d3dx_parameter *param, walk_parameter_dep_func param_func,
3673         void *data);
3674 
3675 static BOOL walk_param_eval_dep(struct d3dx_param_eval *param_eval, walk_parameter_dep_func param_func,
3676         void *data)
3677 {
3678     struct d3dx_parameter **params;
3679     unsigned int i, param_count;
3680 
3681     if (!param_eval)
3682         return FALSE;
3683 
3684     params = param_eval->shader_inputs.inputs_param;
3685     param_count = param_eval->shader_inputs.input_count;
3686     for (i = 0; i < param_count; ++i)
3687     {
3688         if (walk_parameter_dep(params[i], param_func, data))
3689             return TRUE;
3690     }
3691 
3692     params = param_eval->pres.inputs.inputs_param;
3693     param_count = param_eval->pres.inputs.input_count;
3694     for (i = 0; i < param_count; ++i)
3695     {
3696         if (walk_parameter_dep(params[i], param_func, data))
3697             return TRUE;
3698     }
3699     return FALSE;
3700 }
3701 
3702 static BOOL walk_state_dep(struct d3dx_state *state, walk_parameter_dep_func param_func,
3703         void *data)
3704 {
3705     if (state->type == ST_CONSTANT && is_param_type_sampler(state->parameter.type))
3706     {
3707         if (walk_parameter_dep(&state->parameter, param_func, data))
3708             return TRUE;
3709     }
3710     else if (state->type == ST_ARRAY_SELECTOR || state->type == ST_PARAMETER)
3711     {
3712         if (walk_parameter_dep(state->referenced_param, param_func, data))
3713             return TRUE;
3714     }
3715     return walk_param_eval_dep(state->parameter.param_eval, param_func, data);
3716 }
3717 
3718 static BOOL walk_parameter_dep(struct d3dx_parameter *param, walk_parameter_dep_func param_func,
3719         void *data)
3720 {
3721     unsigned int i;
3722     unsigned int member_count;
3723 
3724     param = &param->top_level_param->param;
3725     if (param_func(data, param))
3726         return TRUE;
3727 
3728     if (walk_param_eval_dep(param->param_eval, param_func, data))
3729         return TRUE;
3730 
3731     if (param->class == D3DXPC_OBJECT && is_param_type_sampler(param->type))
3732     {
3733         struct d3dx_sampler *sampler;
3734         unsigned int sampler_idx;
3735         unsigned int samplers_count = max(param->element_count, 1);
3736 
3737         for (sampler_idx = 0; sampler_idx < samplers_count; ++sampler_idx)
3738         {
3739             sampler = param->element_count ? param->members[sampler_idx].data : param->data;
3740             for (i = 0; i < sampler->state_count; ++i)
3741             {
3742                 if (walk_state_dep(&sampler->states[i], param_func, data))
3743                     return TRUE;
3744             }
3745         }
3746         return FALSE;
3747     }
3748 
3749     member_count = param->element_count ? param->element_count : param->member_count;
3750     for (i = 0; i < member_count; ++i)
3751     {
3752         if (walk_param_eval_dep(param->members[i].param_eval, param_func, data))
3753             return TRUE;
3754     }
3755 
3756     return FALSE;
3757 }
3758 
3759 static BOOL is_parameter_used(struct d3dx_parameter *param, struct d3dx_technique *tech)
3760 {
3761     unsigned int i, j;
3762     struct d3dx_pass *pass;
3763 
3764     if (!tech || !param)
3765         return FALSE;
3766 
3767     for (i = 0; i < tech->pass_count; ++i)
3768     {
3769         pass = &tech->passes[i];
3770         for (j = 0; j < pass->state_count; ++j)
3771         {
3772             if (walk_state_dep(&pass->states[j], is_same_parameter, param))
3773                 return TRUE;
3774         }
3775     }
3776     return FALSE;
3777 }
3778 
3779 static BOOL WINAPI d3dx_effect_IsParameterUsed(ID3DXEffect *iface, D3DXHANDLE parameter, D3DXHANDLE technique)
3780 {
3781     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3782     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3783     struct d3dx_technique *tech = get_valid_technique(effect, technique);
3784     BOOL ret;
3785 
3786     TRACE("iface %p, parameter %p, technique %p.\n", iface, parameter, technique);
3787     TRACE("param %p, name %s, tech %p.\n", param, param ? debugstr_a(param->name) : "", tech);
3788 
3789     ret = is_parameter_used(param, tech);
3790     TRACE("Returning %#x.\n", ret);
3791     return ret;
3792 }
3793 
3794 static HRESULT WINAPI d3dx_effect_Begin(ID3DXEffect *iface, UINT *passes, DWORD flags)
3795 {
3796     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3797     struct d3dx_technique *technique = effect->active_technique;
3798 
3799     TRACE("iface %p, passes %p, flags %#x.\n", iface, passes, flags);
3800 
3801     if (technique)
3802     {
3803         if (flags & ~(D3DXFX_DONOTSAVESTATE | D3DXFX_DONOTSAVESAMPLERSTATE | D3DXFX_DONOTSAVESHADERSTATE))
3804             WARN("Invalid flags (%#x) specified.\n", flags);
3805 
3806         if (flags & D3DXFX_DONOTSAVESTATE)
3807         {
3808             TRACE("State capturing disabled.\n");
3809         }
3810         else
3811         {
3812             HRESULT hr;
3813             unsigned int i;
3814 
3815             if (!technique->saved_state)
3816             {
3817                 ID3DXEffectStateManager *manager;
3818 
3819                 manager = effect->manager;
3820                 effect->manager = NULL;
3821                 if (FAILED(hr = IDirect3DDevice9_BeginStateBlock(effect->device)))
3822                     ERR("BeginStateBlock failed, hr %#x.\n", hr);
3823                 for (i = 0; i < technique->pass_count; i++)
3824                     d3dx9_apply_pass_states(effect, &technique->passes[i], TRUE);
3825                 if (FAILED(hr = IDirect3DDevice9_EndStateBlock(effect->device, &technique->saved_state)))
3826                     ERR("EndStateBlock failed, hr %#x.\n", hr);
3827                 effect->manager = manager;
3828             }
3829             if (FAILED(hr = IDirect3DStateBlock9_Capture(technique->saved_state)))
3830                 ERR("StateBlock Capture failed, hr %#x.\n", hr);
3831         }
3832 
3833         if (passes)
3834             *passes = technique->pass_count;
3835         effect->started = TRUE;
3836         effect->begin_flags = flags;
3837 
3838         return D3D_OK;
3839     }
3840 
3841     WARN("Invalid argument supplied.\n");
3842 
3843     return D3DERR_INVALIDCALL;
3844 }
3845 
3846 static HRESULT WINAPI d3dx_effect_BeginPass(ID3DXEffect *iface, UINT pass)
3847 {
3848     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3849     struct d3dx_technique *technique = effect->active_technique;
3850 
3851     TRACE("iface %p, pass %u\n", effect, pass);
3852 
3853     if (technique && pass < technique->pass_count && !effect->active_pass)
3854     {
3855         HRESULT hr;
3856 
3857         memset(effect->current_light, 0, sizeof(effect->current_light));
3858         memset(&effect->current_material, 0, sizeof(effect->current_material));
3859 
3860         if (SUCCEEDED(hr = d3dx9_apply_pass_states(effect, &technique->passes[pass], TRUE)))
3861             effect->active_pass = &technique->passes[pass];
3862         return hr;
3863     }
3864 
3865     WARN("Invalid argument supplied.\n");
3866 
3867     return D3DERR_INVALIDCALL;
3868 }
3869 
3870 static HRESULT WINAPI d3dx_effect_CommitChanges(ID3DXEffect *iface)
3871 {
3872     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3873 
3874     TRACE("iface %p.\n", iface);
3875 
3876     if (!effect->active_pass)
3877     {
3878         WARN("Called without an active pass.\n");
3879         return D3D_OK;
3880     }
3881     return d3dx9_apply_pass_states(effect, effect->active_pass, FALSE);
3882 }
3883 
3884 static HRESULT WINAPI d3dx_effect_EndPass(ID3DXEffect *iface)
3885 {
3886     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
3887 
3888     TRACE("iface %p\n", This);
3889 
3890     if (This->active_pass)
3891     {
3892          This->active_pass = NULL;
3893          return D3D_OK;
3894     }
3895 
3896     WARN("Invalid call.\n");
3897 
3898     return D3DERR_INVALIDCALL;
3899 }
3900 
3901 static HRESULT WINAPI d3dx_effect_End(ID3DXEffect *iface)
3902 {
3903     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3904     struct d3dx_technique *technique = effect->active_technique;
3905 
3906     TRACE("iface %p.\n", iface);
3907 
3908     if (!effect->started)
3909         return D3D_OK;
3910 
3911     if (effect->begin_flags & D3DXFX_DONOTSAVESTATE)
3912     {
3913         TRACE("State restoring disabled.\n");
3914     }
3915     else
3916     {
3917         HRESULT hr;
3918 
3919         if (technique && technique->saved_state)
3920         {
3921             if (FAILED(hr = IDirect3DStateBlock9_Apply(technique->saved_state)))
3922                 ERR("State block apply failed, hr %#x.\n", hr);
3923         }
3924         else
3925             ERR("No saved state.\n");
3926     }
3927 
3928     effect->started = FALSE;
3929 
3930     return D3D_OK;
3931 }
3932 
3933 static HRESULT WINAPI d3dx_effect_GetDevice(ID3DXEffect *iface, struct IDirect3DDevice9 **device)
3934 {
3935     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
3936 
3937     TRACE("iface %p, device %p\n", This, device);
3938 
3939     if (!device)
3940     {
3941         WARN("Invalid argument supplied.\n");
3942         return D3DERR_INVALIDCALL;
3943     }
3944 
3945     IDirect3DDevice9_AddRef(This->device);
3946 
3947     *device = This->device;
3948 
3949     TRACE("Returning device %p\n", *device);
3950 
3951     return S_OK;
3952 }
3953 
3954 static BOOL param_on_lost_device(void *data, struct d3dx_parameter *param)
3955 {
3956     struct IDirect3DVolumeTexture9 *volume_texture;
3957     struct IDirect3DCubeTexture9 *cube_texture;
3958     struct IDirect3DTexture9 *texture;
3959     D3DSURFACE_DESC surface_desc;
3960     D3DVOLUME_DESC volume_desc;
3961 
3962     if (param->class == D3DXPC_OBJECT && !param->element_count)
3963     {
3964         switch (param->type)
3965         {
3966             case D3DXPT_TEXTURE:
3967             case D3DXPT_TEXTURE1D:
3968             case D3DXPT_TEXTURE2D:
3969                 texture = *(IDirect3DTexture9 **)param->data;
3970                 if (!texture)
3971                     return FALSE;
3972                 IDirect3DTexture9_GetLevelDesc(texture, 0, &surface_desc);
3973                 if (surface_desc.Pool != D3DPOOL_DEFAULT)
3974                     return FALSE;
3975                 break;
3976             case D3DXPT_TEXTURE3D:
3977                 volume_texture = *(IDirect3DVolumeTexture9 **)param->data;
3978                 if (!volume_texture)
3979                     return FALSE;
3980                 IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
3981                 if (volume_desc.Pool != D3DPOOL_DEFAULT)
3982                     return FALSE;
3983                 break;
3984             case D3DXPT_TEXTURECUBE:
3985                 cube_texture = *(IDirect3DCubeTexture9 **)param->data;
3986                 if (!cube_texture)
3987                     return FALSE;
3988                 IDirect3DTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
3989                 if (surface_desc.Pool != D3DPOOL_DEFAULT)
3990                     return FALSE;
3991                 break;
3992             default:
3993                 return FALSE;
3994         }
3995         IUnknown_Release(*(IUnknown **)param->data);
3996         *(IUnknown **)param->data = NULL;
3997     }
3998     return FALSE;
3999 }
4000 
4001 static HRESULT WINAPI d3dx_effect_OnLostDevice(ID3DXEffect *iface)
4002 {
4003     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4004     unsigned int i;
4005 
4006     TRACE("iface %p.\n", iface);
4007 
4008     for (i = 0; i < effect->parameter_count; ++i)
4009         walk_parameter_tree(&effect->parameters[i].param, param_on_lost_device, NULL);
4010 
4011     return D3D_OK;
4012 }
4013 
4014 static HRESULT WINAPI d3dx_effect_OnResetDevice(ID3DXEffect *iface)
4015 {
4016     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4017 
4018     FIXME("(%p)->(): stub\n", This);
4019 
4020     return E_NOTIMPL;
4021 }
4022 
4023 static HRESULT WINAPI d3dx_effect_SetStateManager(ID3DXEffect *iface, ID3DXEffectStateManager *manager)
4024 {
4025     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4026 
4027     TRACE("iface %p, manager %p\n", This, manager);
4028 
4029     if (manager) IUnknown_AddRef(manager);
4030     if (This->manager) IUnknown_Release(This->manager);
4031 
4032     This->manager = manager;
4033 
4034     return D3D_OK;
4035 }
4036 
4037 static HRESULT WINAPI d3dx_effect_GetStateManager(ID3DXEffect *iface, ID3DXEffectStateManager **manager)
4038 {
4039     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4040 
4041     TRACE("iface %p, manager %p\n", This, manager);
4042 
4043     if (!manager)
4044     {
4045         WARN("Invalid argument supplied.\n");
4046         return D3DERR_INVALIDCALL;
4047     }
4048 
4049     if (This->manager) IUnknown_AddRef(This->manager);
4050     *manager = This->manager;
4051 
4052     return D3D_OK;
4053 }
4054 
4055 static HRESULT WINAPI d3dx_effect_BeginParameterBlock(ID3DXEffect *iface)
4056 {
4057     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4058 
4059     FIXME("(%p)->(): stub\n", This);
4060 
4061     return E_NOTIMPL;
4062 }
4063 
4064 static D3DXHANDLE WINAPI d3dx_effect_EndParameterBlock(ID3DXEffect *iface)
4065 {
4066     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4067 
4068     FIXME("(%p)->(): stub\n", This);
4069 
4070     return NULL;
4071 }
4072 
4073 static HRESULT WINAPI d3dx_effect_ApplyParameterBlock(ID3DXEffect *iface, D3DXHANDLE parameter_block)
4074 {
4075     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4076 
4077     FIXME("(%p)->(%p): stub\n", This, parameter_block);
4078 
4079     return E_NOTIMPL;
4080 }
4081 
4082 #if D3DX_SDK_VERSION >= 26
4083 static HRESULT WINAPI d3dx_effect_DeleteParameterBlock(ID3DXEffect *iface, D3DXHANDLE parameter_block)
4084 {
4085     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4086 
4087     FIXME("(%p)->(%p): stub\n", This, parameter_block);
4088 
4089     return E_NOTIMPL;
4090 }
4091 #endif
4092 
4093 static HRESULT WINAPI d3dx_effect_CloneEffect(ID3DXEffect *iface, IDirect3DDevice9 *device,
4094         ID3DXEffect **new_effect)
4095 {
4096     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4097 
4098     FIXME("iface %p, device %p, new_effect %p stub.\n", effect, device, new_effect);
4099 
4100     if (!new_effect)
4101         return D3DERR_INVALIDCALL;
4102 
4103     if (effect->flags & D3DXFX_NOT_CLONEABLE)
4104         return E_FAIL;
4105 
4106     if (!device)
4107         return D3DERR_INVALIDCALL;
4108 
4109     return E_NOTIMPL;
4110 }
4111 
4112 #if D3DX_SDK_VERSION >= 27
4113 static HRESULT WINAPI d3dx_effect_SetRawValue(ID3DXEffect *iface, D3DXHANDLE parameter, const void *data,
4114         UINT byte_offset, UINT bytes)
4115 {
4116     FIXME("iface %p, parameter %p, data %p, byte_offset %u, bytes %u stub!\n",
4117             iface, parameter, data, byte_offset, bytes);
4118 
4119     return E_NOTIMPL;
4120 }
4121 #endif
4122 
4123 static const struct ID3DXEffectVtbl ID3DXEffect_Vtbl =
4124 {
4125     /*** IUnknown methods ***/
4126     d3dx_effect_QueryInterface,
4127     d3dx_effect_AddRef,
4128     d3dx_effect_Release,
4129     /*** ID3DXBaseEffect methods ***/
4130     d3dx_effect_GetDesc,
4131     d3dx_effect_GetParameterDesc,
4132     d3dx_effect_GetTechniqueDesc,
4133     d3dx_effect_GetPassDesc,
4134     d3dx_effect_GetFunctionDesc,
4135     d3dx_effect_GetParameter,
4136     d3dx_effect_GetParameterByName,
4137     d3dx_effect_GetParameterBySemantic,
4138     d3dx_effect_GetParameterElement,
4139     d3dx_effect_GetTechnique,
4140     d3dx_effect_GetTechniqueByName,
4141     d3dx_effect_GetPass,
4142     d3dx_effect_GetPassByName,
4143     d3dx_effect_GetFunction,
4144     d3dx_effect_GetFunctionByName,
4145     d3dx_effect_GetAnnotation,
4146     d3dx_effect_GetAnnotationByName,
4147     d3dx_effect_SetValue,
4148     d3dx_effect_GetValue,
4149     d3dx_effect_SetBool,
4150     d3dx_effect_GetBool,
4151     d3dx_effect_SetBoolArray,
4152     d3dx_effect_GetBoolArray,
4153     d3dx_effect_SetInt,
4154     d3dx_effect_GetInt,
4155     d3dx_effect_SetIntArray,
4156     d3dx_effect_GetIntArray,
4157     d3dx_effect_SetFloat,
4158     d3dx_effect_GetFloat,
4159     d3dx_effect_SetFloatArray,
4160     d3dx_effect_GetFloatArray,
4161     d3dx_effect_SetVector,
4162     d3dx_effect_GetVector,
4163     d3dx_effect_SetVectorArray,
4164     d3dx_effect_GetVectorArray,
4165     d3dx_effect_SetMatrix,
4166     d3dx_effect_GetMatrix,
4167     d3dx_effect_SetMatrixArray,
4168     d3dx_effect_GetMatrixArray,
4169     d3dx_effect_SetMatrixPointerArray,
4170     d3dx_effect_GetMatrixPointerArray,
4171     d3dx_effect_SetMatrixTranspose,
4172     d3dx_effect_GetMatrixTranspose,
4173     d3dx_effect_SetMatrixTransposeArray,
4174     d3dx_effect_GetMatrixTransposeArray,
4175     d3dx_effect_SetMatrixTransposePointerArray,
4176     d3dx_effect_GetMatrixTransposePointerArray,
4177     d3dx_effect_SetString,
4178     d3dx_effect_GetString,
4179     d3dx_effect_SetTexture,
4180     d3dx_effect_GetTexture,
4181     d3dx_effect_GetPixelShader,
4182     d3dx_effect_GetVertexShader,
4183     d3dx_effect_SetArrayRange,
4184     /*** ID3DXEffect methods ***/
4185     d3dx_effect_GetPool,
4186     d3dx_effect_SetTechnique,
4187     d3dx_effect_GetCurrentTechnique,
4188     d3dx_effect_ValidateTechnique,
4189     d3dx_effect_FindNextValidTechnique,
4190     d3dx_effect_IsParameterUsed,
4191     d3dx_effect_Begin,
4192     d3dx_effect_BeginPass,
4193     d3dx_effect_CommitChanges,
4194     d3dx_effect_EndPass,
4195     d3dx_effect_End,
4196     d3dx_effect_GetDevice,
4197     d3dx_effect_OnLostDevice,
4198     d3dx_effect_OnResetDevice,
4199     d3dx_effect_SetStateManager,
4200     d3dx_effect_GetStateManager,
4201     d3dx_effect_BeginParameterBlock,
4202     d3dx_effect_EndParameterBlock,
4203     d3dx_effect_ApplyParameterBlock,
4204 #if D3DX_SDK_VERSION >= 26
4205     d3dx_effect_DeleteParameterBlock,
4206 #endif
4207     d3dx_effect_CloneEffect,
4208 #if D3DX_SDK_VERSION >= 27
4209     d3dx_effect_SetRawValue
4210 #endif
4211 };
4212 
4213 static inline struct ID3DXEffectCompilerImpl *impl_from_ID3DXEffectCompiler(ID3DXEffectCompiler *iface)
4214 {
4215     return CONTAINING_RECORD(iface, struct ID3DXEffectCompilerImpl, ID3DXEffectCompiler_iface);
4216 }
4217 
4218 /*** IUnknown methods ***/
4219 static HRESULT WINAPI ID3DXEffectCompilerImpl_QueryInterface(ID3DXEffectCompiler *iface, REFIID riid, void **object)
4220 {
4221     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
4222 
4223     if (IsEqualGUID(riid, &IID_IUnknown) ||
4224         IsEqualGUID(riid, &IID_ID3DXEffectCompiler))
4225     {
4226         iface->lpVtbl->AddRef(iface);
4227         *object = iface;
4228         return S_OK;
4229     }
4230 
4231     ERR("Interface %s not found\n", debugstr_guid(riid));
4232 
4233     return E_NOINTERFACE;
4234 }
4235 
4236 static ULONG WINAPI ID3DXEffectCompilerImpl_AddRef(ID3DXEffectCompiler *iface)
4237 {
4238     struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
4239 
4240     TRACE("iface %p: AddRef from %u\n", iface, This->ref);
4241 
4242     return InterlockedIncrement(&This->ref);
4243 }
4244 
4245 static ULONG WINAPI ID3DXEffectCompilerImpl_Release(ID3DXEffectCompiler *iface)
4246 {
4247     struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface);
4248     ULONG ref = InterlockedDecrement(&This->ref);
4249 
4250     TRACE("iface %p: Release from %u\n", iface, ref + 1);
4251 
4252     if (!ref)
4253     {
4254         HeapFree(GetProcessHeap(), 0, This);
4255     }
4256 
4257     return ref;
4258 }
4259 
4260 /*** ID3DXBaseEffect methods ***/
4261 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetDesc(ID3DXEffectCompiler *iface, D3DXEFFECT_DESC *desc)
4262 {
4263     FIXME("iface %p, desc %p stub!\n", iface, desc);
4264 
4265     return E_NOTIMPL;
4266 }
4267 
4268 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetParameterDesc(ID3DXEffectCompiler *iface,
4269         D3DXHANDLE parameter, D3DXPARAMETER_DESC *desc)
4270 {
4271     FIXME("iface %p, parameter %p, desc %p stub!\n", iface, parameter, desc);
4272 
4273     return E_NOTIMPL;
4274 }
4275 
4276 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetTechniqueDesc(ID3DXEffectCompiler *iface,
4277         D3DXHANDLE technique, D3DXTECHNIQUE_DESC *desc)
4278 {
4279     FIXME("iface %p, technique %p, desc %p stub!\n", iface, technique, desc);
4280 
4281     return E_NOTIMPL;
4282 }
4283 
4284 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetPassDesc(ID3DXEffectCompiler *iface,
4285         D3DXHANDLE pass, D3DXPASS_DESC *desc)
4286 {
4287     FIXME("iface %p, pass %p, desc %p stub!\n", iface, pass, desc);
4288 
4289     return E_NOTIMPL;
4290 }
4291 
4292 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFunctionDesc(ID3DXEffectCompiler *iface,
4293         D3DXHANDLE shader, D3DXFUNCTION_DESC *desc)
4294 {
4295     FIXME("iface %p, shader %p, desc %p stub!\n", iface, shader, desc);
4296 
4297     return E_NOTIMPL;
4298 }
4299 
4300 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameter(ID3DXEffectCompiler *iface,
4301         D3DXHANDLE parameter, UINT index)
4302 {
4303     FIXME("iface %p, parameter %p, index %u stub!\n", iface, parameter, index);
4304 
4305     return NULL;
4306 }
4307 
4308 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterByName(ID3DXEffectCompiler *iface,
4309         D3DXHANDLE parameter, const char *name)
4310 {
4311     FIXME("iface %p, parameter %p, name %s stub!\n", iface, parameter, debugstr_a(name));
4312 
4313     return NULL;
4314 }
4315 
4316 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterBySemantic(ID3DXEffectCompiler *iface,
4317         D3DXHANDLE parameter, const char *semantic)
4318 {
4319     FIXME("iface %p, parameter %p, semantic %s stub!\n", iface, parameter, debugstr_a(semantic));
4320 
4321     return NULL;
4322 }
4323 
4324 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterElement(ID3DXEffectCompiler *iface,
4325         D3DXHANDLE parameter, UINT index)
4326 {
4327     FIXME("iface %p, parameter %p, index %u stub!\n", iface, parameter, index);
4328 
4329     return NULL;
4330 }
4331 
4332 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetTechnique(ID3DXEffectCompiler *iface, UINT index)
4333 {
4334     FIXME("iface %p, index %u stub!\n", iface, index);
4335 
4336     return NULL;
4337 }
4338 
4339 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetTechniqueByName(ID3DXEffectCompiler *iface, const char *name)
4340 {
4341     FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
4342 
4343     return NULL;
4344 }
4345 
4346 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetPass(ID3DXEffectCompiler *iface, D3DXHANDLE technique, UINT index)
4347 {
4348     FIXME("iface %p, technique %p, index %u stub!\n", iface, technique, index);
4349 
4350     return NULL;
4351 }
4352 
4353 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetPassByName(ID3DXEffectCompiler *iface,
4354         D3DXHANDLE technique, const char *name)
4355 {
4356     FIXME("iface %p, technique %p, name %s stub!\n", iface, technique, debugstr_a(name));
4357 
4358     return NULL;
4359 }
4360 
4361 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetFunction(ID3DXEffectCompiler *iface, UINT index)
4362 {
4363     FIXME("iface %p, index %u stub!\n", iface, index);
4364 
4365     return NULL;
4366 }
4367 
4368 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetFunctionByName(ID3DXEffectCompiler *iface, const char *name)
4369 {
4370     FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
4371 
4372     return NULL;
4373 }
4374 
4375 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetAnnotation(ID3DXEffectCompiler *iface,
4376         D3DXHANDLE object, UINT index)
4377 {
4378     FIXME("iface %p, object %p, index %u stub!\n", iface, object, index);
4379 
4380     return NULL;
4381 }
4382 
4383 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetAnnotationByName(ID3DXEffectCompiler *iface,
4384         D3DXHANDLE object, const char *name)
4385 {
4386     FIXME("iface %p, object %p, name %s stub!\n", iface, object, debugstr_a(name));
4387 
4388     return NULL;
4389 }
4390 
4391 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetValue(ID3DXEffectCompiler *iface,
4392         D3DXHANDLE parameter, const void *data, UINT bytes)
4393 {
4394     FIXME("iface %p, parameter %p, data %p, bytes %u stub!\n", iface, parameter, data, bytes);
4395 
4396     return E_NOTIMPL;
4397 }
4398 
4399 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetValue(ID3DXEffectCompiler *iface,
4400         D3DXHANDLE parameter, void *data, UINT bytes)
4401 {
4402     FIXME("iface %p, parameter %p, data %p, bytes %u stub!\n", iface, parameter, data, bytes);
4403 
4404     return E_NOTIMPL;
4405 }
4406 
4407 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetBool(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL b)
4408 {
4409     FIXME("iface %p, parameter %p, b %#x stub!\n", iface, parameter, b);
4410 
4411     return E_NOTIMPL;
4412 }
4413 
4414 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetBool(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL *b)
4415 {
4416     FIXME("iface %p, parameter %p, b %p stub!\n", iface, parameter, b);
4417 
4418     return E_NOTIMPL;
4419 }
4420 
4421 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetBoolArray(ID3DXEffectCompiler *iface,
4422         D3DXHANDLE parameter, const BOOL *b, UINT count)
4423 {
4424     FIXME("iface %p, parameter %p, b %p, count %u stub!\n", iface, parameter, b, count);
4425 
4426     return E_NOTIMPL;
4427 }
4428 
4429 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetBoolArray(ID3DXEffectCompiler *iface,
4430         D3DXHANDLE parameter, BOOL *b, UINT count)
4431 {
4432     FIXME("iface %p, parameter %p, b %p, count %u stub!\n", iface, parameter, b, count);
4433 
4434     return E_NOTIMPL;
4435 }
4436 
4437 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetInt(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, INT n)
4438 {
4439     FIXME("iface %p, parameter %p, n %d stub!\n", iface, parameter, n);
4440 
4441     return E_NOTIMPL;
4442 }
4443 
4444 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetInt(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, INT *n)
4445 {
4446     FIXME("iface %p, parameter %p, n %p stub!\n", iface, parameter, n);
4447 
4448     return E_NOTIMPL;
4449 }
4450 
4451 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetIntArray(ID3DXEffectCompiler *iface,
4452         D3DXHANDLE parameter, const INT *n, UINT count)
4453 {
4454     FIXME("iface %p, parameter %p, n %p, count %u stub!\n", iface, parameter, n, count);
4455 
4456     return E_NOTIMPL;
4457 }
4458 
4459 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetIntArray(ID3DXEffectCompiler *iface,
4460         D3DXHANDLE parameter, INT *n, UINT count)
4461 {
4462     FIXME("iface %p, parameter %p, n %p, count %u stub!\n", iface, parameter, n, count);
4463 
4464     return E_NOTIMPL;
4465 }
4466 
4467 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetFloat(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, float f)
4468 {
4469     FIXME("iface %p, parameter %p, f %.8e stub!\n", iface, parameter, f);
4470 
4471     return E_NOTIMPL;
4472 }
4473 
4474 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFloat(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, float *f)
4475 {
4476     FIXME("iface %p, parameter %p, f %p stub!\n", iface, parameter, f);
4477 
4478     return E_NOTIMPL;
4479 }
4480 
4481 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetFloatArray(ID3DXEffectCompiler *iface,
4482         D3DXHANDLE parameter, const float *f, UINT count)
4483 {
4484     FIXME("iface %p, parameter %p, f %p, count %u stub!\n", iface, parameter, f, count);
4485 
4486     return E_NOTIMPL;
4487 }
4488 
4489 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFloatArray(ID3DXEffectCompiler *iface,
4490         D3DXHANDLE parameter, float *f, UINT count)
4491 {
4492     FIXME("iface %p, parameter %p, f %p, count %u stub!\n", iface, parameter, f, count);
4493 
4494     return E_NOTIMPL;
4495 }
4496 
4497 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetVector(ID3DXEffectCompiler *iface,
4498         D3DXHANDLE parameter, const D3DXVECTOR4 *vector)
4499 {
4500     FIXME("iface %p, parameter %p, vector %p stub!\n", iface, parameter, vector);
4501 
4502     return E_NOTIMPL;
4503 }
4504 
4505 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVector(ID3DXEffectCompiler *iface,
4506         D3DXHANDLE parameter, D3DXVECTOR4 *vector)
4507 {
4508     FIXME("iface %p, parameter %p, vector %p stub!\n", iface, parameter, vector);
4509 
4510     return E_NOTIMPL;
4511 }
4512 
4513 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetVectorArray(ID3DXEffectCompiler *iface,
4514         D3DXHANDLE parameter, const D3DXVECTOR4 *vector, UINT count)
4515 {
4516     FIXME("iface %p, parameter %p, vector %p, count %u stub!\n", iface, parameter, vector, count);
4517 
4518     return E_NOTIMPL;
4519 }
4520 
4521 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVectorArray(ID3DXEffectCompiler *iface,
4522         D3DXHANDLE parameter, D3DXVECTOR4 *vector, UINT count)
4523 {
4524     FIXME("iface %p, parameter %p, vector %p, count %u stub!\n", iface, parameter, vector, count);
4525 
4526     return E_NOTIMPL;
4527 }
4528 
4529 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrix(ID3DXEffectCompiler *iface,
4530         D3DXHANDLE parameter, const D3DXMATRIX *matrix)
4531 {
4532     FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
4533 
4534     return E_NOTIMPL;
4535 }
4536 
4537 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrix(ID3DXEffectCompiler *iface,
4538         D3DXHANDLE parameter, D3DXMATRIX *matrix)
4539 {
4540     FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
4541 
4542     return E_NOTIMPL;
4543 }
4544 
4545 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixArray(ID3DXEffectCompiler *iface,
4546         D3DXHANDLE parameter, const D3DXMATRIX *matrix, UINT count)
4547 {
4548     FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4549 
4550     return E_NOTIMPL;
4551 }
4552 
4553 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixArray(ID3DXEffectCompiler *iface,
4554         D3DXHANDLE parameter, D3DXMATRIX *matrix, UINT count)
4555 {
4556     FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4557 
4558     return E_NOTIMPL;
4559 }
4560 
4561 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixPointerArray(ID3DXEffectCompiler *iface,
4562         D3DXHANDLE parameter, const D3DXMATRIX **matrix, UINT count)
4563 {
4564     FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4565 
4566     return E_NOTIMPL;
4567 }
4568 
4569 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixPointerArray(ID3DXEffectCompiler *iface,
4570         D3DXHANDLE parameter, D3DXMATRIX **matrix, UINT count)
4571 {
4572     FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4573 
4574     return E_NOTIMPL;
4575 }
4576 
4577 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTranspose(ID3DXEffectCompiler *iface,
4578         D3DXHANDLE parameter, const D3DXMATRIX *matrix)
4579 {
4580     FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
4581 
4582     return E_NOTIMPL;
4583 }
4584 
4585 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTranspose(ID3DXEffectCompiler *iface,
4586         D3DXHANDLE parameter, D3DXMATRIX *matrix)
4587 {
4588     FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
4589 
4590     return E_NOTIMPL;
4591 }
4592 
4593 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTransposeArray(ID3DXEffectCompiler *iface,
4594         D3DXHANDLE parameter, const D3DXMATRIX *matrix, UINT count)
4595 {
4596     FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4597 
4598     return E_NOTIMPL;
4599 }
4600 
4601 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTransposeArray(ID3DXEffectCompiler *iface,
4602         D3DXHANDLE parameter, D3DXMATRIX *matrix, UINT count)
4603 {
4604     FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4605 
4606     return E_NOTIMPL;
4607 }
4608 
4609 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTransposePointerArray(ID3DXEffectCompiler *iface,
4610         D3DXHANDLE parameter, const D3DXMATRIX **matrix, UINT count)
4611 {
4612     FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4613 
4614     return E_NOTIMPL;
4615 }
4616 
4617 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTransposePointerArray(ID3DXEffectCompiler *iface,
4618         D3DXHANDLE parameter, D3DXMATRIX **matrix, UINT count)
4619 {
4620     FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4621 
4622     return E_NOTIMPL;
4623 }
4624 
4625 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetString(ID3DXEffectCompiler *iface,
4626         D3DXHANDLE parameter, const char *string)
4627 {
4628     FIXME("iface %p, parameter %p, string %s stub!\n", iface, parameter, debugstr_a(string));
4629 
4630     return E_NOTIMPL;
4631 }
4632 
4633 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetString(ID3DXEffectCompiler *iface,
4634         D3DXHANDLE parameter, const char **string)
4635 {
4636     FIXME("iface %p, parameter %p, string %p stub!\n", iface, parameter, string);
4637 
4638     return E_NOTIMPL;
4639 }
4640 
4641 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetTexture(struct ID3DXEffectCompiler *iface,
4642         D3DXHANDLE parameter, struct IDirect3DBaseTexture9 *texture)
4643 {
4644     FIXME("iface %p, parameter %p, texture %p stub!\n", iface, parameter, texture);
4645 
4646     return E_NOTIMPL;
4647 }
4648 
4649 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetTexture(struct ID3DXEffectCompiler *iface,
4650         D3DXHANDLE parameter, struct IDirect3DBaseTexture9 **texture)
4651 {
4652     FIXME("iface %p, parameter %p, texture %p stub!\n", iface, parameter, texture);
4653 
4654     return E_NOTIMPL;
4655 }
4656 
4657 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetPixelShader(ID3DXEffectCompiler *iface,
4658         D3DXHANDLE parameter, struct IDirect3DPixelShader9 **shader)
4659 {
4660     FIXME("iface %p, parameter %p, shader %p stub!\n", iface, parameter, shader);
4661 
4662     return E_NOTIMPL;
4663 }
4664 
4665 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVertexShader(struct ID3DXEffectCompiler *iface,
4666         D3DXHANDLE parameter, struct IDirect3DVertexShader9 **shader)
4667 {
4668     FIXME("iface %p, parameter %p, shader %p stub!\n", iface, parameter, shader);
4669 
4670     return E_NOTIMPL;
4671 }
4672 
4673 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetArrayRange(ID3DXEffectCompiler *iface,
4674         D3DXHANDLE parameter, UINT start, UINT end)
4675 {
4676     FIXME("iface %p, parameter %p, start %u, end %u stub!\n", iface, parameter, start, end);
4677 
4678     return E_NOTIMPL;
4679 }
4680 
4681 /*** ID3DXEffectCompiler methods ***/
4682 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetLiteral(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL literal)
4683 {
4684     FIXME("iface %p, parameter %p, literal %#x stub!\n", iface, parameter, literal);
4685 
4686     return E_NOTIMPL;
4687 }
4688 
4689 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetLiteral(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL *literal)
4690 {
4691     FIXME("iface %p, parameter %p, literal %p stub!\n", iface, parameter, literal);
4692 
4693     return E_NOTIMPL;
4694 }
4695 
4696 static HRESULT WINAPI ID3DXEffectCompilerImpl_CompileEffect(ID3DXEffectCompiler *iface, DWORD flags,
4697         ID3DXBuffer **effect, ID3DXBuffer **error_msgs)
4698 {
4699     FIXME("iface %p, flags %#x, effect %p, error_msgs %p stub!\n", iface, flags, effect, error_msgs);
4700 
4701     return E_NOTIMPL;
4702 }
4703 
4704 static HRESULT WINAPI ID3DXEffectCompilerImpl_CompileShader(ID3DXEffectCompiler *iface, D3DXHANDLE function,
4705         const char *target, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_msgs,
4706         ID3DXConstantTable **constant_table)
4707 {
4708     FIXME("iface %p, function %p, target %s, flags %#x, shader %p, error_msgs %p, constant_table %p stub!\n",
4709             iface, function, debugstr_a(target), flags, shader, error_msgs, constant_table);
4710 
4711     return E_NOTIMPL;
4712 }
4713 
4714 static const struct ID3DXEffectCompilerVtbl ID3DXEffectCompiler_Vtbl =
4715 {
4716     /*** IUnknown methods ***/
4717     ID3DXEffectCompilerImpl_QueryInterface,
4718     ID3DXEffectCompilerImpl_AddRef,
4719     ID3DXEffectCompilerImpl_Release,
4720     /*** ID3DXBaseEffect methods ***/
4721     ID3DXEffectCompilerImpl_GetDesc,
4722     ID3DXEffectCompilerImpl_GetParameterDesc,
4723     ID3DXEffectCompilerImpl_GetTechniqueDesc,
4724     ID3DXEffectCompilerImpl_GetPassDesc,
4725     ID3DXEffectCompilerImpl_GetFunctionDesc,
4726     ID3DXEffectCompilerImpl_GetParameter,
4727     ID3DXEffectCompilerImpl_GetParameterByName,
4728     ID3DXEffectCompilerImpl_GetParameterBySemantic,
4729     ID3DXEffectCompilerImpl_GetParameterElement,
4730     ID3DXEffectCompilerImpl_GetTechnique,
4731     ID3DXEffectCompilerImpl_GetTechniqueByName,
4732     ID3DXEffectCompilerImpl_GetPass,
4733     ID3DXEffectCompilerImpl_GetPassByName,
4734     ID3DXEffectCompilerImpl_GetFunction,
4735     ID3DXEffectCompilerImpl_GetFunctionByName,
4736     ID3DXEffectCompilerImpl_GetAnnotation,
4737     ID3DXEffectCompilerImpl_GetAnnotationByName,
4738     ID3DXEffectCompilerImpl_SetValue,
4739     ID3DXEffectCompilerImpl_GetValue,
4740     ID3DXEffectCompilerImpl_SetBool,
4741     ID3DXEffectCompilerImpl_GetBool,
4742     ID3DXEffectCompilerImpl_SetBoolArray,
4743     ID3DXEffectCompilerImpl_GetBoolArray,
4744     ID3DXEffectCompilerImpl_SetInt,
4745     ID3DXEffectCompilerImpl_GetInt,
4746     ID3DXEffectCompilerImpl_SetIntArray,
4747     ID3DXEffectCompilerImpl_GetIntArray,
4748     ID3DXEffectCompilerImpl_SetFloat,
4749     ID3DXEffectCompilerImpl_GetFloat,
4750     ID3DXEffectCompilerImpl_SetFloatArray,
4751     ID3DXEffectCompilerImpl_GetFloatArray,
4752     ID3DXEffectCompilerImpl_SetVector,
4753     ID3DXEffectCompilerImpl_GetVector,
4754     ID3DXEffectCompilerImpl_SetVectorArray,
4755     ID3DXEffectCompilerImpl_GetVectorArray,
4756     ID3DXEffectCompilerImpl_SetMatrix,
4757     ID3DXEffectCompilerImpl_GetMatrix,
4758     ID3DXEffectCompilerImpl_SetMatrixArray,
4759     ID3DXEffectCompilerImpl_GetMatrixArray,
4760     ID3DXEffectCompilerImpl_SetMatrixPointerArray,
4761     ID3DXEffectCompilerImpl_GetMatrixPointerArray,
4762     ID3DXEffectCompilerImpl_SetMatrixTranspose,
4763     ID3DXEffectCompilerImpl_GetMatrixTranspose,
4764     ID3DXEffectCompilerImpl_SetMatrixTransposeArray,
4765     ID3DXEffectCompilerImpl_GetMatrixTransposeArray,
4766     ID3DXEffectCompilerImpl_SetMatrixTransposePointerArray,
4767     ID3DXEffectCompilerImpl_GetMatrixTransposePointerArray,
4768     ID3DXEffectCompilerImpl_SetString,
4769     ID3DXEffectCompilerImpl_GetString,
4770     ID3DXEffectCompilerImpl_SetTexture,
4771     ID3DXEffectCompilerImpl_GetTexture,
4772     ID3DXEffectCompilerImpl_GetPixelShader,
4773     ID3DXEffectCompilerImpl_GetVertexShader,
4774     ID3DXEffectCompilerImpl_SetArrayRange,
4775     /*** ID3DXEffectCompiler methods ***/
4776     ID3DXEffectCompilerImpl_SetLiteral,
4777     ID3DXEffectCompilerImpl_GetLiteral,
4778     ID3DXEffectCompilerImpl_CompileEffect,
4779     ID3DXEffectCompilerImpl_CompileShader,
4780 };
4781 
4782 static HRESULT d3dx_parse_sampler(struct d3dx_effect *effect, struct d3dx_sampler *sampler,
4783         const char *data, const char **ptr, struct d3dx_object *objects)
4784 {
4785     HRESULT hr;
4786     UINT i;
4787 
4788     read_dword(ptr, &sampler->state_count);
4789     TRACE("Count: %u\n", sampler->state_count);
4790 
4791     sampler->states = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*sampler->states) * sampler->state_count);
4792     if (!sampler->states)
4793     {
4794         ERR("Out of memory\n");
4795         return E_OUTOFMEMORY;
4796     }
4797 
4798     for (i = 0; i < sampler->state_count; ++i)
4799     {
4800         hr = d3dx_parse_state(effect, &sampler->states[i], data, ptr, objects);
4801         if (hr != D3D_OK)
4802         {
4803             WARN("Failed to parse state %u\n", i);
4804             goto err_out;
4805         }
4806     }
4807 
4808     return D3D_OK;
4809 
4810 err_out:
4811 
4812     for (i = 0; i < sampler->state_count; ++i)
4813     {
4814         free_state(&sampler->states[i]);
4815     }
4816     HeapFree(GetProcessHeap(), 0, sampler->states);
4817     sampler->states = NULL;
4818 
4819     return hr;
4820 }
4821 
4822 static HRESULT d3dx_parse_value(struct d3dx_effect *effect, struct d3dx_parameter *param,
4823         void *value, const char *data, const char **ptr, struct d3dx_object *objects)
4824 {
4825     unsigned int i;
4826     HRESULT hr;
4827     UINT old_size = 0;
4828 
4829     if (param->element_count)
4830     {
4831         param->data = value;
4832 
4833         for (i = 0; i < param->element_count; ++i)
4834         {
4835             struct d3dx_parameter *member = &param->members[i];
4836 
4837             hr = d3dx_parse_value(effect, member, value ? (char *)value + old_size : NULL, data, ptr, objects);
4838             if (hr != D3D_OK)
4839             {
4840                 WARN("Failed to parse value %u\n", i);
4841                 return hr;
4842             }
4843 
4844             old_size += member->bytes;
4845         }
4846 
4847         return D3D_OK;
4848     }
4849 
4850     switch(param->class)
4851     {
4852         case D3DXPC_SCALAR:
4853         case D3DXPC_VECTOR:
4854         case D3DXPC_MATRIX_ROWS:
4855         case D3DXPC_MATRIX_COLUMNS:
4856             param->data = value;
4857             break;
4858 
4859         case D3DXPC_STRUCT:
4860             param->data = value;
4861 
4862             for (i = 0; i < param->member_count; ++i)
4863             {
4864                 struct d3dx_parameter *member = &param->members[i];
4865 
4866                 hr = d3dx_parse_value(effect, member, (char *)value + old_size, data, ptr, objects);
4867                 if (hr != D3D_OK)
4868                 {
4869                     WARN("Failed to parse value %u\n", i);
4870                     return hr;
4871                 }
4872 
4873                 old_size += member->bytes;
4874             }
4875             break;
4876 
4877         case D3DXPC_OBJECT:
4878             switch (param->type)
4879             {
4880                 case D3DXPT_STRING:
4881                 case D3DXPT_TEXTURE:
4882                 case D3DXPT_TEXTURE1D:
4883                 case D3DXPT_TEXTURE2D:
4884                 case D3DXPT_TEXTURE3D:
4885                 case D3DXPT_TEXTURECUBE:
4886                 case D3DXPT_PIXELSHADER:
4887                 case D3DXPT_VERTEXSHADER:
4888                     read_dword(ptr, &param->object_id);
4889                     TRACE("Id: %u\n", param->object_id);
4890                     objects[param->object_id].param = param;
4891                     param->data = value;
4892                     break;
4893 
4894                 case D3DXPT_SAMPLER:
4895                 case D3DXPT_SAMPLER1D:
4896                 case D3DXPT_SAMPLER2D:
4897                 case D3DXPT_SAMPLER3D:
4898                 case D3DXPT_SAMPLERCUBE:
4899                 {
4900                     struct d3dx_sampler *sampler;
4901 
4902                     sampler = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*sampler));
4903                     if (!sampler)
4904                         return E_OUTOFMEMORY;
4905 
4906                     hr = d3dx_parse_sampler(effect, sampler, data, ptr, objects);
4907                     if (hr != D3D_OK)
4908                     {
4909                         HeapFree(GetProcessHeap(), 0, sampler);
4910                         WARN("Failed to parse sampler\n");
4911                         return hr;
4912                     }
4913 
4914                     param->data = sampler;
4915                     break;
4916                 }
4917 
4918                 default:
4919                     FIXME("Unhandled type %s\n", debug_d3dxparameter_type(param->type));
4920                     break;
4921             }
4922             break;
4923 
4924         default:
4925             FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
4926             break;
4927     }
4928 
4929     return D3D_OK;
4930 }
4931 
4932 static HRESULT d3dx_parse_init_value(struct d3dx_effect *effect, struct d3dx_parameter *param,
4933         const char *data, const char *ptr, struct d3dx_object *objects)
4934 {
4935     UINT size = param->bytes;
4936     HRESULT hr;
4937     void *value = NULL;
4938 
4939     TRACE("param size: %u\n", size);
4940 
4941     if (size)
4942     {
4943         value = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
4944         if (!value)
4945         {
4946             ERR("Failed to allocate data memory.\n");
4947             return E_OUTOFMEMORY;
4948         }
4949 
4950         switch(param->class)
4951         {
4952             case D3DXPC_OBJECT:
4953                 break;
4954 
4955             case D3DXPC_SCALAR:
4956             case D3DXPC_VECTOR:
4957             case D3DXPC_MATRIX_ROWS:
4958             case D3DXPC_MATRIX_COLUMNS:
4959             case D3DXPC_STRUCT:
4960                 TRACE("Data: %s.\n", debugstr_an(ptr, size));
4961                 memcpy(value, ptr, size);
4962                 break;
4963 
4964             default:
4965                 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
4966                 break;
4967         }
4968     }
4969 
4970     hr = d3dx_parse_value(effect, param, value, data, &ptr, objects);
4971     if (hr != D3D_OK)
4972     {
4973         WARN("Failed to parse value\n");
4974         HeapFree(GetProcessHeap(), 0, value);
4975         return hr;
4976     }
4977 
4978     return D3D_OK;
4979 }
4980 
4981 static HRESULT d3dx9_parse_name(char **name, const char *ptr)
4982 {
4983     DWORD size;
4984 
4985     read_dword(&ptr, &size);
4986     TRACE("Name size: %#x\n", size);
4987 
4988     if (!size)
4989     {
4990         return D3D_OK;
4991     }
4992 
4993     *name = HeapAlloc(GetProcessHeap(), 0, size);
4994     if (!*name)
4995     {
4996         ERR("Failed to allocate name memory.\n");
4997         return E_OUTOFMEMORY;
4998     }
4999 
5000     TRACE("Name: %s.\n", debugstr_an(ptr, size));
5001     memcpy(*name, ptr, size);
5002 
5003     return D3D_OK;
5004 }
5005 
5006 static HRESULT d3dx9_copy_data(struct d3dx_effect *effect, unsigned int object_id, const char **ptr)
5007 {
5008     struct d3dx_object *object = &effect->objects[object_id];
5009 
5010     if (object->size || object->data)
5011     {
5012         if (object_id)
5013             FIXME("Overwriting object id %u!\n", object_id);
5014         else
5015             TRACE("Overwriting object id 0.\n");
5016 
5017         HeapFree(GetProcessHeap(), 0, object->data);
5018         object->data = NULL;
5019     }
5020 
5021     read_dword(ptr, &object->size);
5022     TRACE("Data size: %#x.\n", object->size);
5023 
5024     if (!object->size)
5025         return D3D_OK;
5026 
5027     object->data = HeapAlloc(GetProcessHeap(), 0, object->size);
5028     if (!object->data)
5029     {
5030         ERR("Failed to allocate object memory.\n");
5031         return E_OUTOFMEMORY;
5032     }
5033 
5034     TRACE("Data: %s.\n", debugstr_an(*ptr, object->size));
5035     memcpy(object->data, *ptr, object->size);
5036 
5037     *ptr += ((object->size + 3) & ~3);
5038 
5039     return D3D_OK;
5040 }
5041 
5042 static void param_set_magic_number(struct d3dx_parameter *param)
5043 {
5044     memcpy(param->magic_string, parameter_magic_string, sizeof(parameter_magic_string));
5045 }
5046 
5047 static int param_rb_compare(const void *key, const struct wine_rb_entry *entry)
5048 {
5049     const char *name = key;
5050     struct d3dx_parameter *param = WINE_RB_ENTRY_VALUE(entry, struct d3dx_parameter, rb_entry);
5051 
5052     return strcmp(name, param->full_name);
5053 }
5054 
5055 static void add_param_to_tree(struct d3dx_effect *effect, struct d3dx_parameter *param,
5056         struct d3dx_parameter *parent, char separator, unsigned int element)
5057 {
5058     const char *parent_name = parent ? parent->full_name : NULL;
5059     unsigned int i;
5060 
5061     TRACE("Adding parameter %p (%s - parent %p, element %u) to the rbtree.\n",
5062             param, debugstr_a(param->name), parent, element);
5063 
5064     if (parent_name)
5065     {
5066         unsigned int parent_name_len = strlen(parent_name);
5067         unsigned int name_len = strlen(param->name);
5068         unsigned int part_str_len;
5069         unsigned int len;
5070         char part_str[16];
5071 
5072         if (separator == '[')
5073         {
5074             sprintf(part_str, "[%u]", element);
5075             part_str_len = strlen(part_str);
5076             name_len = 0;
5077         }
5078         else
5079         {
5080             part_str[0] = separator;
5081             part_str[1] = 0;
5082             part_str_len = 1;
5083         }
5084         len = parent_name_len + part_str_len + name_len + 1;
5085 
5086         if (!(param->full_name = heap_alloc(len)))
5087         {
5088             ERR("Out of memory.\n");
5089             return;
5090         }
5091 
5092         memcpy(param->full_name, parent_name, parent_name_len);
5093         memcpy(param->full_name + parent_name_len, part_str, part_str_len);
5094         memcpy(param->full_name + parent_name_len + part_str_len, param->name, name_len);
5095         param->full_name[len - 1] = 0;
5096     }
5097     else
5098     {
5099         unsigned int len = strlen(param->name) + 1;
5100 
5101         if (!(param->full_name = heap_alloc(len)))
5102         {
5103             ERR("Out of memory.\n");
5104             return;
5105         }
5106 
5107         memcpy(param->full_name, param->name, len);
5108     }
5109     TRACE("Full name is %s.\n", param->full_name);
5110     wine_rb_put(&effect->param_tree, param->full_name, &param->rb_entry);
5111 
5112     if (is_top_level_parameter(param))
5113         for (i = 0; i < param->top_level_param->annotation_count; ++i)
5114             add_param_to_tree(effect, &param->top_level_param->annotations[i], param, '@', 0);
5115 
5116     if (param->element_count)
5117         for (i = 0; i < param->element_count; ++i)
5118             add_param_to_tree(effect, &param->members[i], param, '[', i);
5119     else
5120         for (i = 0; i < param->member_count; ++i)
5121             add_param_to_tree(effect, &param->members[i], param, '.', 0);
5122 }
5123 
5124 static HRESULT d3dx_parse_effect_typedef(struct d3dx_effect *effect, struct d3dx_parameter *param,
5125 	const char *data, const char **ptr, struct d3dx_parameter *parent, UINT flags)
5126 {
5127     DWORD offset;
5128     HRESULT hr;
5129     UINT i;
5130 
5131     param->flags = flags;
5132 
5133     if (!parent)
5134     {
5135         read_dword(ptr, (DWORD *)&param->type);
5136         TRACE("Type: %s\n", debug_d3dxparameter_type(param->type));
5137 
5138         read_dword(ptr, (DWORD *)&param->class);
5139         TRACE("Class: %s\n", debug_d3dxparameter_class(param->class));
5140 
5141         read_dword(ptr, &offset);
5142         TRACE("Type name offset: %#x\n", offset);
5143         hr = d3dx9_parse_name(&param->name, data + offset);
5144         if (hr != D3D_OK)
5145         {
5146             WARN("Failed to parse name\n");
5147             goto err_out;
5148         }
5149 
5150         read_dword(ptr, &offset);
5151         TRACE("Type semantic offset: %#x\n", offset);
5152         hr = d3dx9_parse_name(&param->semantic, data + offset);
5153         if (hr != D3D_OK)
5154         {
5155             WARN("Failed to parse semantic\n");
5156             goto err_out;
5157         }
5158 
5159         read_dword(ptr, &param->element_count);
5160         TRACE("Elements: %u\n", param->element_count);
5161 
5162         switch (param->class)
5163         {
5164             case D3DXPC_VECTOR:
5165                 read_dword(ptr, &param->columns);
5166                 TRACE("Columns: %u\n", param->columns);
5167 
5168                 read_dword(ptr, &param->rows);
5169                 TRACE("Rows: %u\n", param->rows);
5170 
5171                 /* sizeof(DWORD) * rows * columns */
5172                 param->bytes = 4 * param->rows * param->columns;
5173                 break;
5174 
5175             case D3DXPC_SCALAR:
5176             case D3DXPC_MATRIX_ROWS:
5177             case D3DXPC_MATRIX_COLUMNS:
5178                 read_dword(ptr, &param->rows);
5179                 TRACE("Rows: %u\n", param->rows);
5180 
5181                 read_dword(ptr, &param->columns);
5182                 TRACE("Columns: %u\n", param->columns);
5183 
5184                 /* sizeof(DWORD) * rows * columns */
5185                 param->bytes = 4 * param->rows * param->columns;
5186                 break;
5187 
5188             case D3DXPC_STRUCT:
5189                 read_dword(ptr, &param->member_count);
5190                 TRACE("Members: %u\n", param->member_count);
5191                 break;
5192 
5193             case D3DXPC_OBJECT:
5194                 switch (param->type)
5195                 {
5196                     case D3DXPT_STRING:
5197                     case D3DXPT_PIXELSHADER:
5198                     case D3DXPT_VERTEXSHADER:
5199                     case D3DXPT_TEXTURE:
5200                     case D3DXPT_TEXTURE1D:
5201                     case D3DXPT_TEXTURE2D:
5202                     case D3DXPT_TEXTURE3D:
5203                     case D3DXPT_TEXTURECUBE:
5204                         param->bytes = sizeof(void *);
5205                         break;
5206 
5207                     case D3DXPT_SAMPLER:
5208                     case D3DXPT_SAMPLER1D:
5209                     case D3DXPT_SAMPLER2D:
5210                     case D3DXPT_SAMPLER3D:
5211                     case D3DXPT_SAMPLERCUBE:
5212                         param->bytes = 0;
5213                         break;
5214 
5215                     default:
5216                         FIXME("Unhandled type %s\n", debug_d3dxparameter_type(param->type));
5217                         break;
5218                 }
5219                 break;
5220 
5221             default:
5222                 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
5223                 break;
5224         }
5225     }
5226     else
5227     {
5228         /* elements */
5229         param->type = parent->type;
5230         param->class = parent->class;
5231         param->name = parent->name;
5232         param->semantic = parent->semantic;
5233         param->element_count = 0;
5234         param->member_count = parent->member_count;
5235         param->bytes = parent->bytes;
5236         param->rows = parent->rows;
5237         param->columns = parent->columns;
5238     }
5239 
5240     if (param->element_count)
5241     {
5242         unsigned int param_bytes = 0;
5243         const char *save_ptr = *ptr;
5244 
5245         param->members = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*param->members) * param->element_count);
5246         if (!param->members)
5247         {
5248             ERR("Out of memory\n");
5249             hr = E_OUTOFMEMORY;
5250             goto err_out;
5251         }
5252 
5253         for (i = 0; i < param->element_count; ++i)
5254         {
5255             *ptr = save_ptr;
5256 
5257             param_set_magic_number(&param->members[i]);
5258             hr = d3dx_parse_effect_typedef(effect, &param->members[i], data, ptr, param, flags);
5259             if (hr != D3D_OK)
5260             {
5261                 WARN("Failed to parse member %u\n", i);
5262                 goto err_out;
5263             }
5264 
5265             param_bytes += param->members[i].bytes;
5266         }
5267 
5268         param->bytes = param_bytes;
5269     }
5270     else if (param->member_count)
5271     {
5272         param->members = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*param->members) * param->member_count);
5273         if (!param->members)
5274         {
5275             ERR("Out of memory\n");
5276             hr = E_OUTOFMEMORY;
5277             goto err_out;
5278         }
5279 
5280         for (i = 0; i < param->member_count; ++i)
5281         {
5282             param_set_magic_number(&param->members[i]);
5283             hr = d3dx_parse_effect_typedef(effect, &param->members[i], data, ptr, NULL, flags);
5284             if (hr != D3D_OK)
5285             {
5286                 WARN("Failed to parse member %u\n", i);
5287                 goto err_out;
5288             }
5289 
5290             param->bytes += param->members[i].bytes;
5291         }
5292     }
5293     return D3D_OK;
5294 
5295 err_out:
5296 
5297     if (param->members)
5298     {
5299         unsigned int count = param->element_count ? param->element_count : param->member_count;
5300 
5301         for (i = 0; i < count; ++i)
5302             free_parameter(&param->members[i], param->element_count != 0, TRUE);
5303         HeapFree(GetProcessHeap(), 0, param->members);
5304         param->members = NULL;
5305     }
5306 
5307     if (!parent)
5308     {
5309         HeapFree(GetProcessHeap(), 0, param->name);
5310         HeapFree(GetProcessHeap(), 0, param->semantic);
5311     }
5312     param->name = NULL;
5313     param->semantic = NULL;
5314 
5315     return hr;
5316 }
5317 
5318 static HRESULT d3dx_parse_effect_annotation(struct d3dx_effect *effect, struct d3dx_parameter *anno,
5319         const char *data, const char **ptr, struct d3dx_object *objects)
5320 {
5321     DWORD offset;
5322     const char *ptr2;
5323     HRESULT hr;
5324 
5325     anno->flags = D3DX_PARAMETER_ANNOTATION;
5326 
5327     read_dword(ptr, &offset);
5328     TRACE("Typedef offset: %#x\n", offset);
5329     ptr2 = data + offset;
5330     hr = d3dx_parse_effect_typedef(effect, anno, data, &ptr2, NULL, D3DX_PARAMETER_ANNOTATION);
5331     if (hr != D3D_OK)
5332     {
5333         WARN("Failed to parse type definition\n");
5334         return hr;
5335     }
5336 
5337     read_dword(ptr, &offset);
5338     TRACE("Value offset: %#x\n", offset);
5339     hr = d3dx_parse_init_value(effect, anno, data, data + offset, objects);
5340     if (hr != D3D_OK)
5341     {
5342         WARN("Failed to parse value\n");
5343         return hr;
5344     }
5345 
5346     return D3D_OK;
5347 }
5348 
5349 static HRESULT d3dx_parse_state(struct d3dx_effect *effect, struct d3dx_state *state,
5350         const char *data, const char **ptr, struct d3dx_object *objects)
5351 {
5352     DWORD offset;
5353     const char *ptr2;
5354     HRESULT hr;
5355 
5356     state->type = ST_CONSTANT;
5357 
5358     read_dword(ptr, &state->operation);
5359     TRACE("Operation: %#x (%s)\n", state->operation, state_table[state->operation].name);
5360 
5361     read_dword(ptr, &state->index);
5362     TRACE("Index: %#x\n", state->index);
5363 
5364     read_dword(ptr, &offset);
5365     TRACE("Typedef offset: %#x\n", offset);
5366     ptr2 = data + offset;
5367     hr = d3dx_parse_effect_typedef(effect, &state->parameter, data, &ptr2, NULL, 0);
5368     if (hr != D3D_OK)
5369     {
5370         WARN("Failed to parse type definition\n");
5371         goto err_out;
5372     }
5373 
5374     read_dword(ptr, &offset);
5375     TRACE("Value offset: %#x\n", offset);
5376     hr = d3dx_parse_init_value(effect, &state->parameter, data, data + offset, objects);
5377     if (hr != D3D_OK)
5378     {
5379         WARN("Failed to parse value\n");
5380         goto err_out;
5381     }
5382 
5383     return D3D_OK;
5384 
5385 err_out:
5386 
5387     free_parameter(&state->parameter, FALSE, FALSE);
5388 
5389     return hr;
5390 }
5391 
5392 static HRESULT d3dx_parse_effect_parameter(struct d3dx_effect *effect, struct d3dx_top_level_parameter *param,
5393         const char *data, const char **ptr, struct d3dx_object *objects)
5394 {
5395     DWORD offset;
5396     HRESULT hr;
5397     unsigned int i;
5398     const char *ptr2;
5399 
5400     read_dword(ptr, &offset);
5401     TRACE("Typedef offset: %#x.\n", offset);
5402     ptr2 = data + offset;
5403 
5404     read_dword(ptr, &offset);
5405     TRACE("Value offset: %#x.\n", offset);
5406 
5407     read_dword(ptr, &param->param.flags);
5408     TRACE("Flags: %#x.\n", param->param.flags);
5409 
5410     read_dword(ptr, &param->annotation_count);
5411     TRACE("Annotation count: %u.\n", param->annotation_count);
5412 
5413     hr = d3dx_parse_effect_typedef(effect, &param->param, data, &ptr2, NULL, param->param.flags);
5414     if (hr != D3D_OK)
5415     {
5416         WARN("Failed to parse type definition.\n");
5417         return hr;
5418     }
5419 
5420     hr = d3dx_parse_init_value(effect, &param->param, data, data + offset, objects);
5421     if (hr != D3D_OK)
5422     {
5423         WARN("Failed to parse value.\n");
5424         return hr;
5425     }
5426 
5427     if (param->annotation_count)
5428     {
5429         param->annotations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5430                 sizeof(*param->annotations) * param->annotation_count);
5431         if (!param->annotations)
5432         {
5433             ERR("Out of memory.\n");
5434             hr = E_OUTOFMEMORY;
5435             goto err_out;
5436         }
5437 
5438         for (i = 0; i < param->annotation_count; ++i)
5439         {
5440             param_set_magic_number(&param->annotations[i]);
5441             hr = d3dx_parse_effect_annotation(effect, &param->annotations[i], data, ptr, objects);
5442             if (hr != D3D_OK)
5443             {
5444                 WARN("Failed to parse annotation.\n");
5445                 goto err_out;
5446             }
5447         }
5448     }
5449 
5450     return D3D_OK;
5451 
5452 err_out:
5453 
5454     if (param->annotations)
5455     {
5456         for (i = 0; i < param->annotation_count; ++i)
5457             free_parameter(&param->annotations[i], FALSE, FALSE);
5458         HeapFree(GetProcessHeap(), 0, param->annotations);
5459         param->annotations = NULL;
5460     }
5461 
5462     return hr;
5463 }
5464 
5465 static HRESULT d3dx_parse_effect_pass(struct d3dx_effect *effect, struct d3dx_pass *pass,
5466         const char *data, const char **ptr, struct d3dx_object *objects)
5467 {
5468     DWORD offset;
5469     HRESULT hr;
5470     unsigned int i;
5471     struct d3dx_state *states = NULL;
5472     char *name = NULL;
5473 
5474     read_dword(ptr, &offset);
5475     TRACE("Pass name offset: %#x\n", offset);
5476     hr = d3dx9_parse_name(&name, data + offset);
5477     if (hr != D3D_OK)
5478     {
5479         WARN("Failed to parse name\n");
5480         goto err_out;
5481     }
5482 
5483     read_dword(ptr, &pass->annotation_count);
5484     TRACE("Annotation count: %u\n", pass->annotation_count);
5485 
5486     read_dword(ptr, &pass->state_count);
5487     TRACE("State count: %u\n", pass->state_count);
5488 
5489     if (pass->annotation_count)
5490     {
5491         pass->annotations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5492                 sizeof(*pass->annotations) * pass->annotation_count);
5493         if (!pass->annotations)
5494         {
5495             ERR("Out of memory\n");
5496             hr = E_OUTOFMEMORY;
5497             goto err_out;
5498         }
5499 
5500         for (i = 0; i < pass->annotation_count; ++i)
5501         {
5502             param_set_magic_number(&pass->annotations[i]);
5503             hr = d3dx_parse_effect_annotation(effect, &pass->annotations[i], data, ptr, objects);
5504             if (hr != D3D_OK)
5505             {
5506                 WARN("Failed to parse annotation %u\n", i);
5507                 goto err_out;
5508             }
5509         }
5510     }
5511 
5512     if (pass->state_count)
5513     {
5514         states = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*states) * pass->state_count);
5515         if (!states)
5516         {
5517             ERR("Out of memory\n");
5518             hr = E_OUTOFMEMORY;
5519             goto err_out;
5520         }
5521 
5522         for (i = 0; i < pass->state_count; ++i)
5523         {
5524             hr = d3dx_parse_state(effect, &states[i], data, ptr, objects);
5525             if (hr != D3D_OK)
5526             {
5527                 WARN("Failed to parse annotation %u\n", i);
5528                 goto err_out;
5529             }
5530         }
5531     }
5532 
5533     pass->name = name;
5534     pass->states = states;
5535 
5536     return D3D_OK;
5537 
5538 err_out:
5539 
5540     if (pass->annotations)
5541     {
5542         for (i = 0; i < pass->annotation_count; ++i)
5543             free_parameter(&pass->annotations[i], FALSE, FALSE);
5544         HeapFree(GetProcessHeap(), 0, pass->annotations);
5545         pass->annotations = NULL;
5546     }
5547 
5548     if (states)
5549     {
5550         for (i = 0; i < pass->state_count; ++i)
5551         {
5552             free_state(&states[i]);
5553         }
5554         HeapFree(GetProcessHeap(), 0, states);
5555     }
5556 
5557     HeapFree(GetProcessHeap(), 0, name);
5558 
5559     return hr;
5560 }
5561 
5562 static HRESULT d3dx_parse_effect_technique(struct d3dx_effect *effect, struct d3dx_technique *technique,
5563         const char *data, const char **ptr, struct d3dx_object *objects)
5564 {
5565     DWORD offset;
5566     HRESULT hr;
5567     unsigned int i;
5568     char *name = NULL;
5569 
5570     read_dword(ptr, &offset);
5571     TRACE("Technique name offset: %#x\n", offset);
5572     hr = d3dx9_parse_name(&name, data + offset);
5573     if (hr != D3D_OK)
5574     {
5575         WARN("Failed to parse name\n");
5576         goto err_out;
5577     }
5578 
5579     read_dword(ptr, &technique->annotation_count);
5580     TRACE("Annotation count: %u\n", technique->annotation_count);
5581 
5582     read_dword(ptr, &technique->pass_count);
5583     TRACE("Pass count: %u\n", technique->pass_count);
5584 
5585     if (technique->annotation_count)
5586     {
5587         technique->annotations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5588                 sizeof(*technique->annotations) * technique->annotation_count);
5589         if (!technique->annotations)
5590         {
5591             ERR("Out of memory\n");
5592             hr = E_OUTOFMEMORY;
5593             goto err_out;
5594         }
5595 
5596         for (i = 0; i < technique->annotation_count; ++i)
5597         {
5598             param_set_magic_number(&technique->annotations[i]);
5599             hr = d3dx_parse_effect_annotation(effect, &technique->annotations[i], data, ptr, objects);
5600             if (hr != D3D_OK)
5601             {
5602                 WARN("Failed to parse annotation %u\n", i);
5603                 goto err_out;
5604             }
5605         }
5606     }
5607 
5608     if (technique->pass_count)
5609     {
5610         technique->passes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5611                 sizeof(*technique->passes) * technique->pass_count);
5612         if (!technique->passes)
5613         {
5614             ERR("Out of memory\n");
5615             hr = E_OUTOFMEMORY;
5616             goto err_out;
5617         }
5618 
5619         for (i = 0; i < technique->pass_count; ++i)
5620         {
5621             hr = d3dx_parse_effect_pass(effect, &technique->passes[i], data, ptr, objects);
5622             if (hr != D3D_OK)
5623             {
5624                 WARN("Failed to parse pass %u\n", i);
5625                 goto err_out;
5626             }
5627         }
5628     }
5629 
5630     technique->name = name;
5631 
5632     return D3D_OK;
5633 
5634 err_out:
5635 
5636     if (technique->passes)
5637     {
5638         for (i = 0; i < technique->pass_count; ++i)
5639             free_pass(&technique->passes[i]);
5640         HeapFree(GetProcessHeap(), 0, technique->passes);
5641         technique->passes = NULL;
5642     }
5643 
5644     if (technique->annotations)
5645     {
5646         for (i = 0; i < technique->annotation_count; ++i)
5647             free_parameter(&technique->annotations[i], FALSE, FALSE);
5648         HeapFree(GetProcessHeap(), 0, technique->annotations);
5649         technique->annotations = NULL;
5650     }
5651 
5652     HeapFree(GetProcessHeap(), 0, name);
5653 
5654     return hr;
5655 }
5656 
5657 static HRESULT d3dx9_create_object(struct d3dx_effect *effect, struct d3dx_object *object)
5658 {
5659     struct d3dx_parameter *param = object->param;
5660     IDirect3DDevice9 *device = effect->device;
5661     HRESULT hr;
5662 
5663     if (*(char **)param->data)
5664         ERR("Parameter data already allocated.\n");
5665 
5666     switch (param->type)
5667     {
5668         case D3DXPT_STRING:
5669             *(char **)param->data = HeapAlloc(GetProcessHeap(), 0, object->size);
5670             if (!*(char **)param->data)
5671             {
5672                 ERR("Out of memory.\n");
5673                 return E_OUTOFMEMORY;
5674             }
5675             memcpy(*(char **)param->data, object->data, object->size);
5676             break;
5677         case D3DXPT_VERTEXSHADER:
5678             if (FAILED(hr = IDirect3DDevice9_CreateVertexShader(device, object->data,
5679                     (IDirect3DVertexShader9 **)param->data)))
5680             {
5681                 WARN("Failed to create vertex shader.\n");
5682                 object->creation_failed = TRUE;
5683             }
5684             break;
5685         case D3DXPT_PIXELSHADER:
5686             if (FAILED(hr = IDirect3DDevice9_CreatePixelShader(device, object->data,
5687                     (IDirect3DPixelShader9 **)param->data)))
5688             {
5689                 WARN("Failed to create pixel shader.\n");
5690                 object->creation_failed = TRUE;
5691             }
5692             break;
5693         default:
5694             break;
5695     }
5696     return D3D_OK;
5697 }
5698 
5699 static HRESULT d3dx_parse_array_selector(struct d3dx_effect *effect, struct d3dx_state *state,
5700         const char **skip_constants, unsigned int skip_constants_count)
5701 {
5702     DWORD string_size;
5703     struct d3dx_parameter *param = &state->parameter;
5704     struct d3dx_object *object = &effect->objects[param->object_id];
5705     char *ptr = object->data;
5706     HRESULT ret;
5707 
5708     TRACE("Parsing array entry selection state for parameter %p.\n", param);
5709 
5710     string_size = *(DWORD *)ptr;
5711     state->referenced_param = get_parameter_by_name(effect, NULL, ptr + 4);
5712     if (state->referenced_param)
5713     {
5714         TRACE("Mapping to parameter %s.\n", debugstr_a(state->referenced_param->name));
5715     }
5716     else
5717     {
5718         FIXME("Referenced parameter %s not found.\n", ptr + 4);
5719         return D3DXERR_INVALIDDATA;
5720     }
5721     TRACE("Unknown DWORD: 0x%.8x.\n", *(DWORD *)(ptr + string_size));
5722 
5723     if (string_size % sizeof(DWORD))
5724         FIXME("Unaligned string_size %u.\n", string_size);
5725     if (FAILED(ret = d3dx_create_param_eval(effect, (DWORD *)(ptr + string_size) + 1,
5726             object->size - (string_size + sizeof(DWORD)), D3DXPT_INT, &param->param_eval,
5727             get_version_counter_ptr(effect), NULL, 0)))
5728         return ret;
5729     ret = D3D_OK;
5730     param = state->referenced_param;
5731     if (param->type == D3DXPT_VERTEXSHADER || param->type == D3DXPT_PIXELSHADER)
5732     {
5733         unsigned int i;
5734 
5735         for (i = 0; i < param->element_count; i++)
5736         {
5737             if (param->members[i].type != param->type)
5738             {
5739                 FIXME("Unexpected member parameter type %u, expected %u.\n", param->members[i].type, param->type);
5740                 return D3DXERR_INVALIDDATA;
5741             }
5742             if (!param->members[i].param_eval)
5743             {
5744                 TRACE("Creating preshader for object %u.\n", param->members[i].object_id);
5745                 object = &effect->objects[param->members[i].object_id];
5746                 if (FAILED(ret = d3dx_create_param_eval(effect, object->data, object->size, param->type,
5747                         &param->members[i].param_eval, get_version_counter_ptr(effect),
5748                         skip_constants, skip_constants_count)))
5749                     break;
5750             }
5751         }
5752     }
5753     return ret;
5754 }
5755 
5756 static HRESULT d3dx_parse_resource(struct d3dx_effect *effect, const char *data, const char **ptr,
5757         const char **skip_constants, unsigned int skip_constants_count)
5758 {
5759     DWORD technique_index;
5760     DWORD index, state_index, usage, element_index;
5761     struct d3dx_state *state;
5762     struct d3dx_parameter *param;
5763     struct d3dx_object *object;
5764     HRESULT hr = E_FAIL;
5765 
5766     read_dword(ptr, &technique_index);
5767     TRACE("technique_index: %u\n", technique_index);
5768 
5769     read_dword(ptr, &index);
5770     TRACE("index: %u\n", index);
5771 
5772     read_dword(ptr, &element_index);
5773     TRACE("element_index: %u\n", element_index);
5774 
5775     read_dword(ptr, &state_index);
5776     TRACE("state_index: %u\n", state_index);
5777 
5778     read_dword(ptr, &usage);
5779     TRACE("usage: %u\n", usage);
5780 
5781     if (technique_index == 0xffffffff)
5782     {
5783         struct d3dx_parameter *parameter;
5784         struct d3dx_sampler *sampler;
5785 
5786         if (index >= effect->parameter_count)
5787         {
5788             FIXME("Index out of bounds: index %u >= parameter_count %u\n", index, effect->parameter_count);
5789             return E_FAIL;
5790         }
5791 
5792         parameter = &effect->parameters[index].param;
5793         if (element_index != 0xffffffff)
5794         {
5795             if (element_index >= parameter->element_count && parameter->element_count != 0)
5796             {
5797                 FIXME("Index out of bounds: element_index %u >= element_count %u\n", element_index, parameter->element_count);
5798                 return E_FAIL;
5799             }
5800 
5801             if (parameter->element_count)
5802                 parameter = &parameter->members[element_index];
5803         }
5804 
5805         sampler = parameter->data;
5806         if (state_index >= sampler->state_count)
5807         {
5808             FIXME("Index out of bounds: state_index %u >= state_count %u\n", state_index, sampler->state_count);
5809             return E_FAIL;
5810         }
5811 
5812         state = &sampler->states[state_index];
5813     }
5814     else
5815     {
5816         struct d3dx_technique *technique;
5817         struct d3dx_pass *pass;
5818 
5819         if (technique_index >= effect->technique_count)
5820         {
5821             FIXME("Index out of bounds: technique_index %u >= technique_count %u.\n", technique_index,
5822                   effect->technique_count);
5823             return E_FAIL;
5824         }
5825 
5826         technique = &effect->techniques[technique_index];
5827         if (index >= technique->pass_count)
5828         {
5829             FIXME("Index out of bounds: index %u >= pass_count %u\n", index, technique->pass_count);
5830             return E_FAIL;
5831         }
5832 
5833         pass = &technique->passes[index];
5834         if (state_index >= pass->state_count)
5835         {
5836             FIXME("Index out of bounds: state_index %u >= state_count %u\n", state_index, pass->state_count);
5837             return E_FAIL;
5838         }
5839 
5840         state = &pass->states[state_index];
5841     }
5842 
5843     TRACE("State operation %#x (%s).\n", state->operation, state_table[state->operation].name);
5844     param = &state->parameter;
5845     TRACE("Using object id %u.\n", param->object_id);
5846     object = &effect->objects[param->object_id];
5847 
5848     TRACE("Usage %u: class %s, type %s.\n", usage, debug_d3dxparameter_class(param->class),
5849             debug_d3dxparameter_type(param->type));
5850     switch (usage)
5851     {
5852         case 0:
5853             switch (param->type)
5854             {
5855                 case D3DXPT_VERTEXSHADER:
5856                 case D3DXPT_PIXELSHADER:
5857                     state->type = ST_CONSTANT;
5858                     if (FAILED(hr = d3dx9_copy_data(effect, param->object_id, ptr)))
5859                         return hr;
5860 
5861                     if (object->data)
5862                     {
5863                         if (FAILED(hr = d3dx9_create_object(effect, object)))
5864                             return hr;
5865                         if (FAILED(hr = d3dx_create_param_eval(effect, object->data, object->size, param->type,
5866                                 &param->param_eval, get_version_counter_ptr(effect),
5867                                 skip_constants, skip_constants_count)))
5868                             return hr;
5869                     }
5870                     break;
5871 
5872                 case D3DXPT_BOOL:
5873                 case D3DXPT_INT:
5874                 case D3DXPT_FLOAT:
5875                 case D3DXPT_STRING:
5876                     state->type = ST_FXLC;
5877                     if (FAILED(hr = d3dx9_copy_data(effect, param->object_id, ptr)))
5878                         return hr;
5879                     if (FAILED(hr = d3dx_create_param_eval(effect, object->data, object->size, param->type,
5880                             &param->param_eval, get_version_counter_ptr(effect), NULL, 0)))
5881                         return hr;
5882                     break;
5883 
5884                 default:
5885                     FIXME("Unhandled type %s\n", debug_d3dxparameter_type(param->type));
5886                     break;
5887             }
5888             break;
5889 
5890         case 1:
5891             state->type = ST_PARAMETER;
5892             if (FAILED(hr = d3dx9_copy_data(effect, param->object_id, ptr)))
5893                 return hr;
5894 
5895             TRACE("Looking for parameter %s.\n", debugstr_a(object->data));
5896             state->referenced_param = get_parameter_by_name(effect, NULL, object->data);
5897             if (state->referenced_param)
5898             {
5899                 struct d3dx_parameter *refpar = state->referenced_param;
5900 
5901                 TRACE("Mapping to parameter %p, having object id %u.\n", refpar, refpar->object_id);
5902                 if (refpar->type == D3DXPT_VERTEXSHADER || refpar->type == D3DXPT_PIXELSHADER)
5903                 {
5904                     struct d3dx_object *refobj = &effect->objects[refpar->object_id];
5905 
5906                     if (!refpar->param_eval)
5907                     {
5908                         if (FAILED(hr = d3dx_create_param_eval(effect, refobj->data, refobj->size,
5909                                 refpar->type, &refpar->param_eval, get_version_counter_ptr(effect),
5910                                 skip_constants, skip_constants_count)))
5911                             return hr;
5912                     }
5913                 }
5914             }
5915             else
5916             {
5917                 FIXME("Referenced parameter %s not found.\n", (char *)object->data);
5918                 return D3DXERR_INVALIDDATA;
5919             }
5920             break;
5921 
5922         case 2:
5923             state->type = ST_ARRAY_SELECTOR;
5924             if (FAILED(hr = d3dx9_copy_data(effect, param->object_id, ptr)))
5925                 return hr;
5926             hr = d3dx_parse_array_selector(effect, state, skip_constants, skip_constants_count);
5927             break;
5928 
5929         default:
5930             FIXME("Unknown usage %x\n", usage);
5931             break;
5932     }
5933 
5934     return hr;
5935 }
5936 
5937 static BOOL param_set_top_level_param(void *top_level_param, struct d3dx_parameter *param)
5938 {
5939     param->top_level_param = top_level_param;
5940     return FALSE;
5941 }
5942 
5943 static HRESULT d3dx_parse_effect(struct d3dx_effect *effect, const char *data, UINT data_size,
5944         DWORD start, const char **skip_constants, unsigned int skip_constants_count)
5945 {
5946     const char *ptr = data + start;
5947     UINT stringcount, resourcecount;
5948     HRESULT hr;
5949     UINT i;
5950 
5951     read_dword(&ptr, &effect->parameter_count);
5952     TRACE("Parameter count: %u.\n", effect->parameter_count);
5953 
5954     read_dword(&ptr, &effect->technique_count);
5955     TRACE("Technique count: %u.\n", effect->technique_count);
5956 
5957     skip_dword_unknown(&ptr, 1);
5958 
5959     read_dword(&ptr, &effect->object_count);
5960     TRACE("Object count: %u.\n", effect->object_count);
5961 
5962     effect->objects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5963             sizeof(*effect->objects) * effect->object_count);
5964     if (!effect->objects)
5965     {
5966         ERR("Out of memory.\n");
5967         hr = E_OUTOFMEMORY;
5968         goto err_out;
5969     }
5970 
5971     wine_rb_init(&effect->param_tree, param_rb_compare);
5972     if (effect->parameter_count)
5973     {
5974         effect->parameters = heap_alloc_zero(sizeof(*effect->parameters) * effect->parameter_count);
5975         if (!effect->parameters)
5976         {
5977             ERR("Out of memory.\n");
5978             hr = E_OUTOFMEMORY;
5979             goto err_out;
5980         }
5981 
5982         for (i = 0; i < effect->parameter_count; ++i)
5983         {
5984             param_set_magic_number(&effect->parameters[i].param);
5985             hr = d3dx_parse_effect_parameter(effect, &effect->parameters[i], data, &ptr, effect->objects);
5986             if (hr != D3D_OK)
5987             {
5988                 WARN("Failed to parse parameter %u.\n", i);
5989                 goto err_out;
5990             }
5991             walk_parameter_tree(&effect->parameters[i].param, param_set_top_level_param, &effect->parameters[i]);
5992             add_param_to_tree(effect, &effect->parameters[i].param, NULL, 0, 0);
5993         }
5994     }
5995 
5996     if (effect->technique_count)
5997     {
5998         effect->techniques = heap_alloc_zero(sizeof(*effect->techniques) * effect->technique_count);
5999         if (!effect->techniques)
6000         {
6001             ERR("Out of memory.\n");
6002             hr = E_OUTOFMEMORY;
6003             goto err_out;
6004         }
6005 
6006         for (i = 0; i < effect->technique_count; ++i)
6007         {
6008             TRACE("Parsing technique %u.\n", i);
6009             hr = d3dx_parse_effect_technique(effect, &effect->techniques[i], data, &ptr, effect->objects);
6010             if (hr != D3D_OK)
6011             {
6012                 WARN("Failed to parse technique %u.\n", i);
6013                 goto err_out;
6014             }
6015         }
6016     }
6017 
6018     read_dword(&ptr, &stringcount);
6019     TRACE("String count: %u.\n", stringcount);
6020 
6021     read_dword(&ptr, &resourcecount);
6022     TRACE("Resource count: %u.\n", resourcecount);
6023 
6024     for (i = 0; i < stringcount; ++i)
6025     {
6026         DWORD id;
6027 
6028         read_dword(&ptr, &id);
6029         TRACE("id: %u.\n", id);
6030 
6031         if (FAILED(hr = d3dx9_copy_data(effect, id, &ptr)))
6032             goto err_out;
6033 
6034         if (effect->objects[id].data)
6035         {
6036             if (FAILED(hr = d3dx9_create_object(effect, &effect->objects[id])))
6037                 goto err_out;
6038         }
6039     }
6040 
6041     for (i = 0; i < resourcecount; ++i)
6042     {
6043         TRACE("parse resource %u.\n", i);
6044 
6045         hr = d3dx_parse_resource(effect, data, &ptr, skip_constants, skip_constants_count);
6046         if (hr != D3D_OK)
6047         {
6048             WARN("Failed to parse resource %u.\n", i);
6049             goto err_out;
6050         }
6051     }
6052 
6053     for (i = 0; i < effect->parameter_count; ++i)
6054     {
6055         if (FAILED(hr = d3dx_pool_sync_shared_parameter(effect->pool, &effect->parameters[i])))
6056             goto err_out;
6057         effect->parameters[i].version_counter = get_version_counter_ptr(effect);
6058         set_dirty(&effect->parameters[i].param);
6059     }
6060     return D3D_OK;
6061 
6062 err_out:
6063 
6064     if (effect->techniques)
6065     {
6066         for (i = 0; i < effect->technique_count; ++i)
6067             free_technique(&effect->techniques[i]);
6068         heap_free(effect->techniques);
6069         effect->techniques = NULL;
6070     }
6071 
6072     if (effect->parameters)
6073     {
6074         for (i = 0; i < effect->parameter_count; ++i)
6075         {
6076             free_top_level_parameter(&effect->parameters[i]);
6077         }
6078         heap_free(effect->parameters);
6079         effect->parameters = NULL;
6080     }
6081 
6082     if (effect->objects)
6083     {
6084         for (i = 0; i < effect->object_count; ++i)
6085         {
6086             free_object(&effect->objects[i]);
6087         }
6088         HeapFree(GetProcessHeap(), 0, effect->objects);
6089         effect->objects = NULL;
6090     }
6091 
6092     return hr;
6093 }
6094 
6095 #define INITIAL_CONST_NAMES_SIZE 4
6096 
6097 static char *next_valid_constant_name(char **string)
6098 {
6099     char *ret = *string;
6100     char *next;
6101 
6102     while (*ret && !isalpha(*ret) && *ret != '_')
6103         ++ret;
6104     if (!*ret)
6105         return NULL;
6106 
6107     next = ret + 1;
6108     while (isalpha(*next) || isdigit(*next) || *next == '_')
6109         ++next;
6110     if (*next)
6111         *next++ = 0;
6112     *string = next;
6113     return ret;
6114 }
6115 
6116 static const char **parse_skip_constants_string(char *skip_constants_string, unsigned int *names_count)
6117 {
6118     const char **names, **new_alloc;
6119     const char *name;
6120     char *s;
6121     unsigned int size = INITIAL_CONST_NAMES_SIZE;
6122 
6123     names = HeapAlloc(GetProcessHeap(), 0, sizeof(*names) * size);
6124     if (!names)
6125         return NULL;
6126 
6127     *names_count = 0;
6128     s = skip_constants_string;
6129     while ((name = next_valid_constant_name(&s)))
6130     {
6131         if (*names_count == size)
6132         {
6133             size *= 2;
6134             new_alloc = HeapReAlloc(GetProcessHeap(), 0, names, sizeof(*names) * size);
6135             if (!new_alloc)
6136             {
6137                 HeapFree(GetProcessHeap(), 0, names);
6138                 return NULL;
6139             }
6140             names = new_alloc;
6141         }
6142         names[(*names_count)++] = name;
6143     }
6144     new_alloc = HeapReAlloc(GetProcessHeap(), 0, names, *names_count * sizeof(*names));
6145     if (!new_alloc)
6146         return names;
6147     return new_alloc;
6148 }
6149 
6150 static HRESULT d3dx9_effect_init(struct d3dx_effect *effect, struct IDirect3DDevice9 *device,
6151         const char *data, SIZE_T data_size, const D3D_SHADER_MACRO *defines, ID3DInclude *include,
6152         UINT eflags, ID3DBlob **errors, struct ID3DXEffectPool *pool, const char *skip_constants_string)
6153 {
6154 #if D3DX_SDK_VERSION <= 36
6155     UINT compile_flags = D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY;
6156 #else
6157     UINT compile_flags = 0;
6158 #endif
6159     struct d3dx9_base_effect *base = &effect->base_effect;
6160     ID3DBlob *bytecode = NULL, *temp_errors = NULL;
6161     unsigned int skip_constants_count = 0;
6162     char *skip_constants_buffer = NULL;
6163     const char **skip_constants = NULL;
6164     const char *ptr = data;
6165     DWORD tag, offset;
6166     unsigned int i, j;
6167     HRESULT hr;
6168 
6169     TRACE("effect %p, device %p, data %p, data_size %lu, defines %p, include %p, eflags %#x, errors %p, "
6170             "pool %p, skip_constants %s.\n",
6171             effect, device, data, data_size, defines, include, eflags, errors, pool,
6172             debugstr_a(skip_constants_string));
6173 
6174     effect->ID3DXEffect_iface.lpVtbl = &ID3DXEffect_Vtbl;
6175     effect->ref = 1;
6176 
6177     if (pool)
6178     {
6179         pool->lpVtbl->AddRef(pool);
6180         effect->pool = impl_from_ID3DXEffectPool(pool);
6181     }
6182 
6183     IDirect3DDevice9_AddRef(device);
6184     effect->device = device;
6185 
6186     base->effect = effect;
6187     effect->flags = eflags;
6188 
6189     read_dword(&ptr, &tag);
6190     TRACE("Tag: %x\n", tag);
6191 
6192     if (tag != d3dx9_effect_version(9, 1))
6193     {
6194         TRACE("HLSL ASCII effect, trying to compile it.\n");
6195         hr = D3DCompile(data, data_size, NULL, defines, include,
6196                 NULL, "fx_2_0", compile_flags, eflags, &bytecode, &temp_errors);
6197         if (FAILED(hr))
6198         {
6199             WARN("Failed to compile ASCII effect.\n");
6200             if (bytecode)
6201                 ID3D10Blob_Release(bytecode);
6202             if (temp_errors)
6203             {
6204                 const char *error_string = ID3D10Blob_GetBufferPointer(temp_errors);
6205                 const char *string_ptr;
6206 
6207                 while (*error_string)
6208                 {
6209                     string_ptr = error_string;
6210                     while (*string_ptr && *string_ptr != '\n' && *string_ptr != '\r'
6211                            && string_ptr - error_string < 80)
6212                         ++string_ptr;
6213                     TRACE("%s\n", debugstr_an(error_string, string_ptr - error_string));
6214                     error_string = string_ptr;
6215                     while (*error_string == '\n' || *error_string == '\r')
6216                         ++error_string;
6217                 }
6218             }
6219             if (errors)
6220                 *errors = temp_errors;
6221             else if (temp_errors)
6222                 ID3D10Blob_Release(temp_errors);
6223             return hr;
6224         }
6225         if (!bytecode)
6226         {
6227             FIXME("No output from effect compilation.\n");
6228             return D3DERR_INVALIDCALL;
6229         }
6230         if (errors)
6231             *errors = temp_errors;
6232         else if (temp_errors)
6233             ID3D10Blob_Release(temp_errors);
6234 
6235         ptr = ID3D10Blob_GetBufferPointer(bytecode);
6236         read_dword(&ptr, &tag);
6237         TRACE("Tag: %x\n", tag);
6238     }
6239 
6240     if (skip_constants_string)
6241     {
6242         skip_constants_buffer = HeapAlloc(GetProcessHeap(), 0,
6243                 sizeof(*skip_constants_buffer) * (strlen(skip_constants_string) + 1));
6244         if (!skip_constants_buffer)
6245         {
6246             if (bytecode)
6247                 ID3D10Blob_Release(bytecode);
6248             return E_OUTOFMEMORY;
6249         }
6250         strcpy(skip_constants_buffer, skip_constants_string);
6251 
6252         if (!(skip_constants = parse_skip_constants_string(skip_constants_buffer, &skip_constants_count)))
6253         {
6254             HeapFree(GetProcessHeap(), 0, skip_constants_buffer);
6255             if (bytecode)
6256                 ID3D10Blob_Release(bytecode);
6257             return E_OUTOFMEMORY;
6258         }
6259     }
6260     read_dword(&ptr, &offset);
6261     TRACE("Offset: %x\n", offset);
6262 
6263     hr = d3dx_parse_effect(effect, ptr, data_size, offset, skip_constants, skip_constants_count);
6264     if (bytecode)
6265         ID3D10Blob_Release(bytecode);
6266     if (hr != D3D_OK)
6267     {
6268         FIXME("Failed to parse effect.\n");
6269         HeapFree(GetProcessHeap(), 0, skip_constants_buffer);
6270         HeapFree(GetProcessHeap(), 0, skip_constants);
6271         return hr;
6272     }
6273 
6274     for (i = 0; i < skip_constants_count; ++i)
6275     {
6276         struct d3dx_parameter *param;
6277         param = get_parameter_by_name(effect, NULL, skip_constants[i]);
6278         if (param)
6279         {
6280             for (j = 0; j < effect->technique_count; ++j)
6281             {
6282                 if (is_parameter_used(param, &effect->techniques[j]))
6283                 {
6284                     WARN("skip_constants parameter %s is used in technique %u.\n",
6285                             debugstr_a(skip_constants[i]), j);
6286                     HeapFree(GetProcessHeap(), 0, skip_constants_buffer);
6287                     HeapFree(GetProcessHeap(), 0, skip_constants);
6288                     return D3DERR_INVALIDCALL;
6289                 }
6290             }
6291         }
6292         else
6293         {
6294             TRACE("skip_constants parameter %s not found.\n",
6295                     debugstr_a(skip_constants[i]));
6296         }
6297     }
6298 
6299     HeapFree(GetProcessHeap(), 0, skip_constants_buffer);
6300     HeapFree(GetProcessHeap(), 0, skip_constants);
6301 
6302     /* initialize defaults - check because of unsupported ascii effects */
6303     if (effect->techniques)
6304     {
6305         effect->active_technique = &effect->techniques[0];
6306         effect->active_pass = NULL;
6307     }
6308 
6309     return D3D_OK;
6310 }
6311 
6312 HRESULT WINAPI D3DXCreateEffectEx(struct IDirect3DDevice9 *device, const void *srcdata, UINT srcdatalen,
6313         const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skip_constants, DWORD flags,
6314         struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilation_errors)
6315 {
6316     struct d3dx_effect *object;
6317     HRESULT hr;
6318 
6319     TRACE("device %p, srcdata %p, srcdatalen %u, defines %p, include %p,"
6320             " skip_constants %p, flags %#x, pool %p, effect %p, compilation_errors %p.\n",
6321             device, srcdata, srcdatalen, defines, include,
6322             skip_constants, flags, pool, effect, compilation_errors);
6323 
6324     if (compilation_errors)
6325         *compilation_errors = NULL;
6326 
6327     if (!device || !srcdata)
6328         return D3DERR_INVALIDCALL;
6329 
6330     if (!srcdatalen)
6331         return E_FAIL;
6332 
6333     /* Native dll allows effect to be null so just return D3D_OK after doing basic checks */
6334     if (!effect)
6335         return D3D_OK;
6336 
6337     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6338     if (!object)
6339         return E_OUTOFMEMORY;
6340 
6341     hr = d3dx9_effect_init(object, device, srcdata, srcdatalen, (const D3D_SHADER_MACRO *)defines,
6342             (ID3DInclude *)include, flags, (ID3DBlob **)compilation_errors, pool, skip_constants);
6343     if (FAILED(hr))
6344     {
6345         WARN("Failed to create effect object, hr %#x.\n", hr);
6346         d3dx_effect_cleanup(object);
6347         return hr;
6348     }
6349 
6350     *effect = &object->ID3DXEffect_iface;
6351 
6352     TRACE("Created ID3DXEffect %p\n", object);
6353 
6354     return D3D_OK;
6355 }
6356 
6357 HRESULT WINAPI D3DXCreateEffect(struct IDirect3DDevice9 *device, const void *srcdata, UINT srcdatalen,
6358         const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags,
6359         struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilation_errors)
6360 {
6361     TRACE("(%p, %p, %u, %p, %p, %#x, %p, %p, %p): Forwarded to D3DXCreateEffectEx\n", device, srcdata, srcdatalen, defines,
6362         include, flags, pool, effect, compilation_errors);
6363 
6364     return D3DXCreateEffectEx(device, srcdata, srcdatalen, defines, include, NULL, flags, pool, effect, compilation_errors);
6365 }
6366 
6367 static HRESULT d3dx9_effect_compiler_init(struct ID3DXEffectCompilerImpl *compiler,
6368         const char *data, SIZE_T data_size, const D3D_SHADER_MACRO *defines, ID3DInclude *include,
6369         UINT eflags, ID3DBlob **error_messages)
6370 {
6371     TRACE("compiler %p, data %p, data_size %lu, defines %p, include %p, eflags %#x, error_messages %p.\n",
6372             compiler, data, data_size, defines, include, eflags, error_messages);
6373 
6374     compiler->ID3DXEffectCompiler_iface.lpVtbl = &ID3DXEffectCompiler_Vtbl;
6375     compiler->ref = 1;
6376 
6377     FIXME("ID3DXEffectCompiler implementation is only a stub.\n");
6378 
6379     return D3D_OK;
6380 }
6381 
6382 HRESULT WINAPI D3DXCreateEffectCompiler(const char *srcdata, UINT srcdatalen, const D3DXMACRO *defines,
6383         ID3DXInclude *include, DWORD flags, ID3DXEffectCompiler **compiler, ID3DXBuffer **parse_errors)
6384 {
6385     struct ID3DXEffectCompilerImpl *object;
6386     HRESULT hr;
6387 
6388     TRACE("srcdata %p, srcdatalen %u, defines %p, include %p, flags %#x, compiler %p, parse_errors %p\n",
6389             srcdata, srcdatalen, defines, include, flags, compiler, parse_errors);
6390 
6391     if (!srcdata || !compiler)
6392     {
6393         WARN("Invalid arguments supplied\n");
6394         return D3DERR_INVALIDCALL;
6395     }
6396 
6397     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6398     if (!object)
6399         return E_OUTOFMEMORY;
6400 
6401     hr = d3dx9_effect_compiler_init(object, srcdata, srcdatalen, (const D3D_SHADER_MACRO *)defines,
6402             (ID3DInclude *)include, flags, (ID3DBlob **)parse_errors);
6403     if (FAILED(hr))
6404     {
6405         WARN("Failed to initialize effect compiler\n");
6406         HeapFree(GetProcessHeap(), 0, object);
6407         return hr;
6408     }
6409 
6410     *compiler = &object->ID3DXEffectCompiler_iface;
6411 
6412     TRACE("Created ID3DXEffectCompiler %p\n", object);
6413 
6414     return D3D_OK;
6415 }
6416 
6417 /*** IUnknown methods ***/
6418 static HRESULT WINAPI d3dx_effect_pool_QueryInterface(ID3DXEffectPool *iface, REFIID riid, void **object)
6419 {
6420     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
6421 
6422     if (IsEqualGUID(riid, &IID_IUnknown) ||
6423         IsEqualGUID(riid, &IID_ID3DXEffectPool))
6424     {
6425         iface->lpVtbl->AddRef(iface);
6426         *object = iface;
6427         return S_OK;
6428     }
6429 
6430     WARN("Interface %s not found\n", debugstr_guid(riid));
6431 
6432     return E_NOINTERFACE;
6433 }
6434 
6435 static ULONG WINAPI d3dx_effect_pool_AddRef(ID3DXEffectPool *iface)
6436 {
6437     struct d3dx_effect_pool *pool = impl_from_ID3DXEffectPool(iface);
6438     ULONG refcount = InterlockedIncrement(&pool->refcount);
6439 
6440     TRACE("%p increasing refcount to %u.\n", pool, refcount);
6441 
6442     return refcount;
6443 }
6444 
6445 static void free_effect_pool(struct d3dx_effect_pool *pool)
6446 {
6447     unsigned int i;
6448 
6449     for (i = 0; i < pool->size; ++i)
6450     {
6451         if (pool->shared_data[i].count)
6452         {
6453             unsigned int j;
6454 
6455             WARN("Releasing pool with referenced parameters.\n");
6456 
6457             param_set_data_pointer(&pool->shared_data[i].parameters[0]->param, NULL, FALSE, TRUE);
6458             pool->shared_data[i].parameters[0]->shared_data = NULL;
6459 
6460             for (j = 1; j < pool->shared_data[i].count; ++j)
6461             {
6462                 walk_parameter_tree(&pool->shared_data[i].parameters[j]->param, param_zero_data_func, NULL);
6463                 pool->shared_data[i].parameters[j]->shared_data = NULL;
6464             }
6465             HeapFree(GetProcessHeap(), 0, pool->shared_data[i].parameters);
6466         }
6467     }
6468     HeapFree(GetProcessHeap(), 0, pool->shared_data);
6469     HeapFree(GetProcessHeap(), 0, pool);
6470 }
6471 
6472 static ULONG WINAPI d3dx_effect_pool_Release(ID3DXEffectPool *iface)
6473 {
6474     struct d3dx_effect_pool *pool = impl_from_ID3DXEffectPool(iface);
6475     ULONG refcount = InterlockedDecrement(&pool->refcount);
6476 
6477     TRACE("%p decreasing refcount to %u.\n", pool, refcount);
6478 
6479     if (!refcount)
6480         free_effect_pool(pool);
6481 
6482     return refcount;
6483 }
6484 
6485 static const struct ID3DXEffectPoolVtbl ID3DXEffectPool_Vtbl =
6486 {
6487     /*** IUnknown methods ***/
6488     d3dx_effect_pool_QueryInterface,
6489     d3dx_effect_pool_AddRef,
6490     d3dx_effect_pool_Release
6491 };
6492 
6493 HRESULT WINAPI D3DXCreateEffectPool(ID3DXEffectPool **pool)
6494 {
6495     struct d3dx_effect_pool *object;
6496 
6497     TRACE("pool %p.\n", pool);
6498 
6499     if (!pool)
6500         return D3DERR_INVALIDCALL;
6501 
6502     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6503     if (!object)
6504         return E_OUTOFMEMORY;
6505 
6506     object->ID3DXEffectPool_iface.lpVtbl = &ID3DXEffectPool_Vtbl;
6507     object->refcount = 1;
6508 
6509     *pool = &object->ID3DXEffectPool_iface;
6510 
6511     return S_OK;
6512 }
6513 
6514 HRESULT WINAPI D3DXCreateEffectFromFileExW(struct IDirect3DDevice9 *device, const WCHAR *srcfile,
6515         const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skipconstants, DWORD flags,
6516         struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors)
6517 {
6518     struct d3dx_include_from_file include_from_file;
6519     const void *buffer;
6520     unsigned int size;
6521     char *filename_a;
6522     HRESULT ret;
6523 
6524     TRACE("device %p, srcfile %s, defines %p, include %p, skipconstants %s, "
6525             "flags %#x, pool %p, effect %p, compilationerrors %p.\n",
6526             device, debugstr_w(srcfile), defines, include, debugstr_a(skipconstants),
6527             flags, pool, effect, compilationerrors);
6528 
6529     if (!device || !srcfile)
6530         return D3DERR_INVALIDCALL;
6531 
6532     if (!include)
6533     {
6534         include_from_file.ID3DXInclude_iface.lpVtbl = &d3dx_include_from_file_vtbl;
6535         include = &include_from_file.ID3DXInclude_iface;
6536     }
6537 
6538     size = WideCharToMultiByte(CP_ACP, 0, srcfile, -1, NULL, 0, NULL, NULL);
6539     filename_a = heap_alloc(size);
6540     if (!filename_a)
6541         return E_OUTOFMEMORY;
6542     WideCharToMultiByte(CP_ACP, 0, srcfile, -1, filename_a, size, NULL, NULL);
6543 
6544     EnterCriticalSection(&from_file_mutex);
6545     ret = ID3DXInclude_Open(include, D3DXINC_LOCAL, filename_a, NULL, &buffer, &size);
6546     if (FAILED(ret))
6547     {
6548         LeaveCriticalSection(&from_file_mutex);
6549         heap_free(filename_a);
6550         return D3DXERR_INVALIDDATA;
6551     }
6552 
6553     ret = D3DXCreateEffectEx(device, buffer, size, defines, include, skipconstants, flags, pool,
6554             effect, compilationerrors);
6555 
6556     ID3DXInclude_Close(include, buffer);
6557     LeaveCriticalSection(&from_file_mutex);
6558     heap_free(filename_a);
6559     return ret;
6560 }
6561 
6562 HRESULT WINAPI D3DXCreateEffectFromFileExA(struct IDirect3DDevice9 *device, const char *srcfile,
6563         const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skipconstants, DWORD flags,
6564         struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors)
6565 {
6566     WCHAR *srcfileW;
6567     HRESULT ret;
6568     DWORD len;
6569 
6570     TRACE("device %p, srcfile %s, defines %p, include %p, skipconstants %s, "
6571             "flags %#x, pool %p, effect %p, compilationerrors %p.\n",
6572             device, debugstr_a(srcfile), defines, include, debugstr_a(skipconstants),
6573             flags, pool, effect, compilationerrors);
6574 
6575     if (!srcfile)
6576         return D3DERR_INVALIDCALL;
6577 
6578     len = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0);
6579     srcfileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(*srcfileW));
6580     MultiByteToWideChar(CP_ACP, 0, srcfile, -1, srcfileW, len);
6581 
6582     ret = D3DXCreateEffectFromFileExW(device, srcfileW, defines, include, skipconstants, flags, pool, effect, compilationerrors);
6583     HeapFree(GetProcessHeap(), 0, srcfileW);
6584 
6585     return ret;
6586 }
6587 
6588 HRESULT WINAPI D3DXCreateEffectFromFileW(struct IDirect3DDevice9 *device, const WCHAR *srcfile,
6589         const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags, struct ID3DXEffectPool *pool,
6590         struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors)
6591 {
6592     TRACE("(void): relay\n");
6593     return D3DXCreateEffectFromFileExW(device, srcfile, defines, include, NULL, flags, pool, effect, compilationerrors);
6594 }
6595 
6596 HRESULT WINAPI D3DXCreateEffectFromFileA(struct IDirect3DDevice9 *device, const char *srcfile,
6597         const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags, struct ID3DXEffectPool *pool,
6598         struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors)
6599 {
6600     TRACE("(void): relay\n");
6601     return D3DXCreateEffectFromFileExA(device, srcfile, defines, include, NULL, flags, pool, effect, compilationerrors);
6602 }
6603 
6604 HRESULT WINAPI D3DXCreateEffectFromResourceExW(struct IDirect3DDevice9 *device, HMODULE srcmodule,
6605         const WCHAR *srcresource, const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skipconstants,
6606         DWORD flags, struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors)
6607 {
6608     HRSRC resinfo;
6609     void *buffer;
6610     DWORD size;
6611 
6612     TRACE("device %p, srcmodule %p, srcresource %s, defines %p, include %p, skipconstants %s, "
6613             "flags %#x, pool %p, effect %p, compilationerrors %p.\n",
6614             device, srcmodule, debugstr_w(srcresource), defines, include, debugstr_a(skipconstants),
6615             flags, pool, effect, compilationerrors);
6616 
6617     if (!device)
6618         return D3DERR_INVALIDCALL;
6619 
6620     if (!(resinfo = FindResourceW(srcmodule, srcresource, (const WCHAR *)RT_RCDATA)))
6621         return D3DXERR_INVALIDDATA;
6622 
6623     if (FAILED(load_resource_into_memory(srcmodule, resinfo, &buffer, &size)))
6624         return D3DXERR_INVALIDDATA;
6625 
6626     return D3DXCreateEffectEx(device, buffer, size, defines, include,
6627             skipconstants, flags, pool, effect, compilationerrors);
6628 }
6629 
6630 HRESULT WINAPI D3DXCreateEffectFromResourceExA(struct IDirect3DDevice9 *device, HMODULE srcmodule,
6631         const char *srcresource, const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skipconstants,
6632         DWORD flags, struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors)
6633 {
6634     HRSRC resinfo;
6635     void *buffer;
6636     DWORD size;
6637 
6638     TRACE("device %p, srcmodule %p, srcresource %s, defines %p, include %p, skipconstants %s, "
6639             "flags %#x, pool %p, effect %p, compilationerrors %p.\n",
6640             device, srcmodule, debugstr_a(srcresource), defines, include, debugstr_a(skipconstants),
6641             flags, pool, effect, compilationerrors);
6642 
6643     if (!device)
6644         return D3DERR_INVALIDCALL;
6645 
6646     if (!(resinfo = FindResourceA(srcmodule, srcresource, (const char *)RT_RCDATA)))
6647         return D3DXERR_INVALIDDATA;
6648 
6649     if (FAILED(load_resource_into_memory(srcmodule, resinfo, &buffer, &size)))
6650         return D3DXERR_INVALIDDATA;
6651 
6652     return D3DXCreateEffectEx(device, buffer, size, defines, include,
6653             skipconstants, flags, pool, effect, compilationerrors);
6654 }
6655 
6656 HRESULT WINAPI D3DXCreateEffectFromResourceW(struct IDirect3DDevice9 *device, HMODULE srcmodule,
6657         const WCHAR *srcresource, const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags,
6658         struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors)
6659 {
6660     TRACE("(void): relay\n");
6661     return D3DXCreateEffectFromResourceExW(device, srcmodule, srcresource, defines, include, NULL, flags, pool, effect, compilationerrors);
6662 }
6663 
6664 HRESULT WINAPI D3DXCreateEffectFromResourceA(struct IDirect3DDevice9 *device, HMODULE srcmodule,
6665         const char *srcresource, const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags,
6666         struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors)
6667 {
6668     TRACE("(void): relay\n");
6669     return D3DXCreateEffectFromResourceExA(device, srcmodule, srcresource, defines, include, NULL, flags, pool, effect, compilationerrors);
6670 }
6671 
6672 HRESULT WINAPI D3DXCreateEffectCompilerFromFileW(const WCHAR *srcfile, const D3DXMACRO *defines,
6673         ID3DXInclude *include, DWORD flags, ID3DXEffectCompiler **effectcompiler, ID3DXBuffer **parseerrors)
6674 {
6675     void *buffer;
6676     HRESULT ret;
6677     DWORD size;
6678 
6679     TRACE("srcfile %s, defines %p, include %p, flags %#x, effectcompiler %p, parseerrors %p.\n",
6680             debugstr_w(srcfile), defines, include, flags, effectcompiler, parseerrors);
6681 
6682     if (!srcfile)
6683         return D3DERR_INVALIDCALL;
6684 
6685     ret = map_view_of_file(srcfile, &buffer, &size);
6686 
6687     if (FAILED(ret))
6688         return D3DXERR_INVALIDDATA;
6689 
6690     ret = D3DXCreateEffectCompiler(buffer, size, defines, include, flags, effectcompiler, parseerrors);
6691     UnmapViewOfFile(buffer);
6692 
6693     return ret;
6694 }
6695 
6696 HRESULT WINAPI D3DXCreateEffectCompilerFromFileA(const char *srcfile, const D3DXMACRO *defines,
6697         ID3DXInclude *include, DWORD flags, ID3DXEffectCompiler **effectcompiler, ID3DXBuffer **parseerrors)
6698 {
6699     WCHAR *srcfileW;
6700     HRESULT ret;
6701     DWORD len;
6702 
6703     TRACE("srcfile %s, defines %p, include %p, flags %#x, effectcompiler %p, parseerrors %p.\n",
6704             debugstr_a(srcfile), defines, include, flags, effectcompiler, parseerrors);
6705 
6706     if (!srcfile)
6707         return D3DERR_INVALIDCALL;
6708 
6709     len = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0);
6710     srcfileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(*srcfileW));
6711     MultiByteToWideChar(CP_ACP, 0, srcfile, -1, srcfileW, len);
6712 
6713     ret = D3DXCreateEffectCompilerFromFileW(srcfileW, defines, include, flags, effectcompiler, parseerrors);
6714     HeapFree(GetProcessHeap(), 0, srcfileW);
6715 
6716     return ret;
6717 }
6718 
6719 HRESULT WINAPI D3DXCreateEffectCompilerFromResourceA(HMODULE srcmodule, const char *srcresource,
6720         const D3DXMACRO *defines, ID3DXInclude *include, DWORD flags,
6721         ID3DXEffectCompiler **effectcompiler, ID3DXBuffer **parseerrors)
6722 {
6723     HRSRC resinfo;
6724     void *buffer;
6725     DWORD size;
6726 
6727     TRACE("srcmodule %p, srcresource %s, defines %p, include %p, flags %#x, effectcompiler %p, parseerrors %p.\n",
6728             srcmodule, debugstr_a(srcresource), defines, include, flags, effectcompiler, parseerrors);
6729 
6730     if (!(resinfo = FindResourceA(srcmodule, srcresource, (const char *)RT_RCDATA)))
6731         return D3DXERR_INVALIDDATA;
6732 
6733     if (FAILED(load_resource_into_memory(srcmodule, resinfo, &buffer, &size)))
6734         return D3DXERR_INVALIDDATA;
6735 
6736     return D3DXCreateEffectCompiler(buffer, size, defines, include, flags, effectcompiler, parseerrors);
6737 }
6738 
6739 HRESULT WINAPI D3DXCreateEffectCompilerFromResourceW(HMODULE srcmodule, const WCHAR *srcresource,
6740         const D3DXMACRO *defines, ID3DXInclude *include, DWORD flags,
6741         ID3DXEffectCompiler **effectcompiler, ID3DXBuffer **parseerrors)
6742 {
6743     HRSRC resinfo;
6744     void *buffer;
6745     DWORD size;
6746 
6747     TRACE("srcmodule %p, srcresource %s, defines %p, include %p, flags %#x, effectcompiler %p, parseerrors %p.\n",
6748             srcmodule, debugstr_w(srcresource), defines, include, flags, effectcompiler, parseerrors);
6749 
6750     if (!(resinfo = FindResourceW(srcmodule, srcresource, (const WCHAR *)RT_RCDATA)))
6751         return D3DXERR_INVALIDDATA;
6752 
6753     if (FAILED(load_resource_into_memory(srcmodule, resinfo, &buffer, &size)))
6754         return D3DXERR_INVALIDDATA;
6755 
6756     return D3DXCreateEffectCompiler(buffer, size, defines, include, flags, effectcompiler, parseerrors);
6757 }
6758 
6759 HRESULT WINAPI D3DXDisassembleEffect(ID3DXEffect *effect, BOOL enable_color_code, ID3DXBuffer **disassembly)
6760 {
6761     FIXME("(%p, %u, %p): stub\n", effect, enable_color_code, disassembly);
6762 
6763     return D3DXERR_INVALIDDATA;
6764 }
6765