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