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