cmd: DIR command outputs free space for the path.
[wine.git] / dlls / d3dx9_36 / effect.c
blobdb40bc249cde531abf29d29f882e3c1653aad68e
1 /*
2 * Copyright 2010 Christian Costa
3 * Copyright 2011 Rico Schüller
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <stdbool.h>
21 #include <stdio.h>
22 #include <assert.h>
24 #include "d3dx9_private.h"
25 #include "d3dcompiler.h"
26 #include "winternl.h"
27 #include "wine/list.h"
29 /* Constants for special INT/FLOAT conversation */
30 #define INT_FLOAT_MULTI 255.0f
31 #define INT_FLOAT_MULTI_INVERSE (1/INT_FLOAT_MULTI)
33 static const char parameter_magic_string[4] = {'@', '!', '#', '\xFF'};
34 static const char parameter_block_magic_string[4] = {'@', '!', '#', '\xFE'};
36 #define PARAMETER_FLAG_SHARED 1
38 #define INITIAL_POOL_SIZE 16
39 #define INITIAL_PARAM_BLOCK_SIZE 1024
41 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
43 enum STATE_CLASS
45 SC_LIGHTENABLE,
46 SC_FVF,
47 SC_LIGHT,
48 SC_MATERIAL,
49 SC_NPATCHMODE,
50 SC_PIXELSHADER,
51 SC_RENDERSTATE,
52 SC_SETSAMPLER,
53 SC_SAMPLERSTATE,
54 SC_TEXTURE,
55 SC_TEXTURESTAGE,
56 SC_TRANSFORM,
57 SC_VERTEXSHADER,
58 SC_SHADERCONST,
59 SC_UNKNOWN,
62 enum MATERIAL_TYPE
64 MT_DIFFUSE,
65 MT_AMBIENT,
66 MT_SPECULAR,
67 MT_EMISSIVE,
68 MT_POWER,
71 enum LIGHT_TYPE
73 LT_TYPE,
74 LT_DIFFUSE,
75 LT_SPECULAR,
76 LT_AMBIENT,
77 LT_POSITION,
78 LT_DIRECTION,
79 LT_RANGE,
80 LT_FALLOFF,
81 LT_ATTENUATION0,
82 LT_ATTENUATION1,
83 LT_ATTENUATION2,
84 LT_THETA,
85 LT_PHI,
88 enum SHADER_CONSTANT_TYPE
90 SCT_VSFLOAT,
91 SCT_VSBOOL,
92 SCT_VSINT,
93 SCT_PSFLOAT,
94 SCT_PSBOOL,
95 SCT_PSINT,
98 enum STATE_TYPE
100 ST_CONSTANT,
101 ST_PARAMETER,
102 ST_FXLC,
103 ST_ARRAY_SELECTOR,
106 struct d3dx_object
108 unsigned int size;
109 void *data;
110 struct d3dx_parameter *param;
111 BOOL creation_failed;
114 struct d3dx_state
116 unsigned int operation;
117 unsigned int index;
118 enum STATE_TYPE type;
119 struct d3dx_parameter parameter;
120 struct d3dx_parameter *referenced_param;
123 struct d3dx_sampler
125 UINT state_count;
126 struct d3dx_state *states;
129 struct d3dx_pass
131 char *name;
132 unsigned int state_count;
133 unsigned int annotation_count;
135 struct d3dx_state *states;
136 struct d3dx_parameter *annotations;
138 ULONG64 update_version;
141 struct d3dx_technique
143 char *name;
144 unsigned int pass_count;
145 unsigned int annotation_count;
147 struct d3dx_parameter *annotations;
148 struct d3dx_pass *passes;
150 struct IDirect3DStateBlock9 *saved_state;
153 struct d3dx_parameter_block
155 char magic_string[ARRAY_SIZE(parameter_block_magic_string)];
156 struct d3dx_effect *effect;
157 struct list entry;
158 size_t size;
159 size_t offset;
160 BYTE *buffer;
163 struct d3dx_recorded_parameter
165 struct d3dx_parameter *param;
166 unsigned int bytes;
169 struct d3dx_effect
171 ID3DXEffect ID3DXEffect_iface;
172 LONG ref;
174 unsigned int technique_count;
175 unsigned int object_count;
176 struct d3dx_technique *techniques;
177 struct d3dx_object *objects;
178 DWORD flags;
180 struct d3dx_parameters_store params;
182 struct ID3DXEffectStateManager *manager;
183 struct IDirect3DDevice9 *device;
184 struct d3dx_effect_pool *pool;
185 struct d3dx_technique *active_technique;
186 struct d3dx_pass *active_pass;
187 BOOL started;
188 DWORD begin_flags;
189 ULONG64 version_counter;
191 D3DLIGHT9 current_light[8];
192 unsigned int light_updated;
193 D3DMATERIAL9 current_material;
194 BOOL material_updated;
196 struct list parameter_block_list;
197 struct d3dx_parameter_block *current_parameter_block;
199 char *source;
200 SIZE_T source_size;
201 char *skip_constants_string;
204 #define INITIAL_SHARED_DATA_SIZE 4
206 struct d3dx_effect_pool
208 ID3DXEffectPool ID3DXEffectPool_iface;
209 LONG refcount;
211 struct d3dx_shared_data *shared_data;
212 unsigned int size;
214 ULONG64 version_counter;
217 struct ID3DXEffectCompilerImpl
219 ID3DXEffectCompiler ID3DXEffectCompiler_iface;
220 LONG ref;
223 static HRESULT d3dx9_effect_init_from_dxbc(struct d3dx_effect *effect,
224 struct IDirect3DDevice9 *device, const char *data, SIZE_T data_size,
225 unsigned int flags, struct ID3DXEffectPool *pool, const char *skip_constants_string);
226 static HRESULT d3dx_parse_state(struct d3dx_effect *effect, struct d3dx_state *state,
227 const char *data, const char **ptr, struct d3dx_object *objects);
228 static void free_parameter(struct d3dx_parameter *param, BOOL element, BOOL child);
230 typedef BOOL (*walk_parameter_dep_func)(void *data, struct d3dx_parameter *param);
232 static const struct
234 enum STATE_CLASS class;
235 UINT op;
236 const char *name;
238 state_table[] =
240 /* Render states */
241 {SC_RENDERSTATE, D3DRS_ZENABLE, "D3DRS_ZENABLE"}, /* 0x0 */
242 {SC_RENDERSTATE, D3DRS_FILLMODE, "D3DRS_FILLMODE"},
243 {SC_RENDERSTATE, D3DRS_SHADEMODE, "D3DRS_SHADEMODE"},
244 {SC_RENDERSTATE, D3DRS_ZWRITEENABLE, "D3DRS_ZWRITEENABLE"},
245 {SC_RENDERSTATE, D3DRS_ALPHATESTENABLE, "D3DRS_ALPHATESTENABLE"},
246 {SC_RENDERSTATE, D3DRS_LASTPIXEL, "D3DRS_LASTPIXEL"},
247 {SC_RENDERSTATE, D3DRS_SRCBLEND, "D3DRS_SRCBLEND"},
248 {SC_RENDERSTATE, D3DRS_DESTBLEND, "D3DRS_DESTBLEND"},
249 {SC_RENDERSTATE, D3DRS_CULLMODE, "D3DRS_CULLMODE"},
250 {SC_RENDERSTATE, D3DRS_ZFUNC, "D3DRS_ZFUNC"},
251 {SC_RENDERSTATE, D3DRS_ALPHAREF, "D3DRS_ALPHAREF"},
252 {SC_RENDERSTATE, D3DRS_ALPHAFUNC, "D3DRS_ALPHAFUNC"},
253 {SC_RENDERSTATE, D3DRS_DITHERENABLE, "D3DRS_DITHERENABLE"},
254 {SC_RENDERSTATE, D3DRS_ALPHABLENDENABLE, "D3DRS_ALPHABLENDENABLE"},
255 {SC_RENDERSTATE, D3DRS_FOGENABLE, "D3DRS_FOGENABLE"},
256 {SC_RENDERSTATE, D3DRS_SPECULARENABLE, "D3DRS_SPECULARENABLE"},
257 {SC_RENDERSTATE, D3DRS_FOGCOLOR, "D3DRS_FOGCOLOR"}, /* 0x10 */
258 {SC_RENDERSTATE, D3DRS_FOGTABLEMODE, "D3DRS_FOGTABLEMODE"},
259 {SC_RENDERSTATE, D3DRS_FOGSTART, "D3DRS_FOGSTART"},
260 {SC_RENDERSTATE, D3DRS_FOGEND, "D3DRS_FOGEND"},
261 {SC_RENDERSTATE, D3DRS_FOGDENSITY, "D3DRS_FOGDENSITY"},
262 {SC_RENDERSTATE, D3DRS_RANGEFOGENABLE, "D3DRS_RANGEFOGENABLE"},
263 {SC_RENDERSTATE, D3DRS_STENCILENABLE, "D3DRS_STENCILENABLE"},
264 {SC_RENDERSTATE, D3DRS_STENCILFAIL, "D3DRS_STENCILFAIL"},
265 {SC_RENDERSTATE, D3DRS_STENCILZFAIL, "D3DRS_STENCILZFAIL"},
266 {SC_RENDERSTATE, D3DRS_STENCILPASS, "D3DRS_STENCILPASS"},
267 {SC_RENDERSTATE, D3DRS_STENCILFUNC, "D3DRS_STENCILFUNC"},
268 {SC_RENDERSTATE, D3DRS_STENCILREF, "D3DRS_STENCILREF"},
269 {SC_RENDERSTATE, D3DRS_STENCILMASK, "D3DRS_STENCILMASK"},
270 {SC_RENDERSTATE, D3DRS_STENCILWRITEMASK, "D3DRS_STENCILWRITEMASK"},
271 {SC_RENDERSTATE, D3DRS_TEXTUREFACTOR, "D3DRS_TEXTUREFACTOR"},
272 {SC_RENDERSTATE, D3DRS_WRAP0, "D3DRS_WRAP0"},
273 {SC_RENDERSTATE, D3DRS_WRAP1, "D3DRS_WRAP1"}, /* 0x20 */
274 {SC_RENDERSTATE, D3DRS_WRAP2, "D3DRS_WRAP2"},
275 {SC_RENDERSTATE, D3DRS_WRAP3, "D3DRS_WRAP3"},
276 {SC_RENDERSTATE, D3DRS_WRAP4, "D3DRS_WRAP4"},
277 {SC_RENDERSTATE, D3DRS_WRAP5, "D3DRS_WRAP5"},
278 {SC_RENDERSTATE, D3DRS_WRAP6, "D3DRS_WRAP6"},
279 {SC_RENDERSTATE, D3DRS_WRAP7, "D3DRS_WRAP7"},
280 {SC_RENDERSTATE, D3DRS_WRAP8, "D3DRS_WRAP8"},
281 {SC_RENDERSTATE, D3DRS_WRAP9, "D3DRS_WRAP9"},
282 {SC_RENDERSTATE, D3DRS_WRAP10, "D3DRS_WRAP10"},
283 {SC_RENDERSTATE, D3DRS_WRAP11, "D3DRS_WRAP11"},
284 {SC_RENDERSTATE, D3DRS_WRAP12, "D3DRS_WRAP12"},
285 {SC_RENDERSTATE, D3DRS_WRAP13, "D3DRS_WRAP13"},
286 {SC_RENDERSTATE, D3DRS_WRAP14, "D3DRS_WRAP14"},
287 {SC_RENDERSTATE, D3DRS_WRAP15, "D3DRS_WRAP15"},
288 {SC_RENDERSTATE, D3DRS_CLIPPING, "D3DRS_CLIPPING"},
289 {SC_RENDERSTATE, D3DRS_LIGHTING, "D3DRS_LIGHTING"}, /* 0x30 */
290 {SC_RENDERSTATE, D3DRS_AMBIENT, "D3DRS_AMBIENT"},
291 {SC_RENDERSTATE, D3DRS_FOGVERTEXMODE, "D3DRS_FOGVERTEXMODE"},
292 {SC_RENDERSTATE, D3DRS_COLORVERTEX, "D3DRS_COLORVERTEX"},
293 {SC_RENDERSTATE, D3DRS_LOCALVIEWER, "D3DRS_LOCALVIEWER"},
294 {SC_RENDERSTATE, D3DRS_NORMALIZENORMALS, "D3DRS_NORMALIZENORMALS"},
295 {SC_RENDERSTATE, D3DRS_DIFFUSEMATERIALSOURCE, "D3DRS_DIFFUSEMATERIALSOURCE"},
296 {SC_RENDERSTATE, D3DRS_SPECULARMATERIALSOURCE, "D3DRS_SPECULARMATERIALSOURCE"},
297 {SC_RENDERSTATE, D3DRS_AMBIENTMATERIALSOURCE, "D3DRS_AMBIENTMATERIALSOURCE"},
298 {SC_RENDERSTATE, D3DRS_EMISSIVEMATERIALSOURCE, "D3DRS_EMISSIVEMATERIALSOURCE"},
299 {SC_RENDERSTATE, D3DRS_VERTEXBLEND, "D3DRS_VERTEXBLEND"},
300 {SC_RENDERSTATE, D3DRS_CLIPPLANEENABLE, "D3DRS_CLIPPLANEENABLE"},
301 {SC_RENDERSTATE, D3DRS_POINTSIZE, "D3DRS_POINTSIZE"},
302 {SC_RENDERSTATE, D3DRS_POINTSIZE_MIN, "D3DRS_POINTSIZE_MIN"},
303 {SC_RENDERSTATE, D3DRS_POINTSIZE_MAX, "D3DRS_POINTSIZE_MAX"},
304 {SC_RENDERSTATE, D3DRS_POINTSPRITEENABLE, "D3DRS_POINTSPRITEENABLE"},
305 {SC_RENDERSTATE, D3DRS_POINTSCALEENABLE, "D3DRS_POINTSCALEENABLE"}, /* 0x40 */
306 {SC_RENDERSTATE, D3DRS_POINTSCALE_A, "D3DRS_POINTSCALE_A"},
307 {SC_RENDERSTATE, D3DRS_POINTSCALE_B, "D3DRS_POINTSCALE_B"},
308 {SC_RENDERSTATE, D3DRS_POINTSCALE_C, "D3DRS_POINTSCALE_C"},
309 {SC_RENDERSTATE, D3DRS_MULTISAMPLEANTIALIAS, "D3DRS_MULTISAMPLEANTIALIAS"},
310 {SC_RENDERSTATE, D3DRS_MULTISAMPLEMASK, "D3DRS_MULTISAMPLEMASK"},
311 {SC_RENDERSTATE, D3DRS_PATCHEDGESTYLE, "D3DRS_PATCHEDGESTYLE"},
312 {SC_RENDERSTATE, D3DRS_DEBUGMONITORTOKEN, "D3DRS_DEBUGMONITORTOKEN"},
313 {SC_RENDERSTATE, D3DRS_INDEXEDVERTEXBLENDENABLE, "D3DRS_INDEXEDVERTEXBLENDENABLE"},
314 {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE, "D3DRS_COLORWRITEENABLE"},
315 {SC_RENDERSTATE, D3DRS_TWEENFACTOR, "D3DRS_TWEENFACTOR"},
316 {SC_RENDERSTATE, D3DRS_BLENDOP, "D3DRS_BLENDOP"},
317 {SC_RENDERSTATE, D3DRS_POSITIONDEGREE, "D3DRS_POSITIONDEGREE"},
318 {SC_RENDERSTATE, D3DRS_NORMALDEGREE, "D3DRS_NORMALDEGREE"},
319 {SC_RENDERSTATE, D3DRS_SCISSORTESTENABLE, "D3DRS_SCISSORTESTENABLE"},
320 {SC_RENDERSTATE, D3DRS_SLOPESCALEDEPTHBIAS, "D3DRS_SLOPESCALEDEPTHBIAS"},
321 {SC_RENDERSTATE, D3DRS_ANTIALIASEDLINEENABLE, "D3DRS_ANTIALIASEDLINEENABLE"}, /* 0x50 */
322 {SC_RENDERSTATE, D3DRS_MINTESSELLATIONLEVEL, "D3DRS_MINTESSELLATIONLEVEL"},
323 {SC_RENDERSTATE, D3DRS_MAXTESSELLATIONLEVEL, "D3DRS_MAXTESSELLATIONLEVEL"},
324 {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_X, "D3DRS_ADAPTIVETESS_X"},
325 {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_Y, "D3DRS_ADAPTIVETESS_Y"},
326 {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_Z, "D3DRS_ADAPTIVETESS_Z"},
327 {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_W, "D3DRS_ADAPTIVETESS_W"},
328 {SC_RENDERSTATE, D3DRS_ENABLEADAPTIVETESSELLATION, "D3DRS_ENABLEADAPTIVETESSELLATION"},
329 {SC_RENDERSTATE, D3DRS_TWOSIDEDSTENCILMODE, "D3DRS_TWOSIDEDSTENCILMODE"},
330 {SC_RENDERSTATE, D3DRS_CCW_STENCILFAIL, "D3DRS_CCW_STENCILFAIL"},
331 {SC_RENDERSTATE, D3DRS_CCW_STENCILZFAIL, "D3DRS_CCW_STENCILZFAIL"},
332 {SC_RENDERSTATE, D3DRS_CCW_STENCILPASS, "D3DRS_CCW_STENCILPASS"},
333 {SC_RENDERSTATE, D3DRS_CCW_STENCILFUNC, "D3DRS_CCW_STENCILFUNC"},
334 {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE1, "D3DRS_COLORWRITEENABLE1"},
335 {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE2, "D3DRS_COLORWRITEENABLE2"},
336 {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE3, "D3DRS_COLORWRITEENABLE3"},
337 {SC_RENDERSTATE, D3DRS_BLENDFACTOR, "D3DRS_BLENDFACTOR"}, /* 0x60 */
338 {SC_RENDERSTATE, D3DRS_SRGBWRITEENABLE, "D3DRS_SRGBWRITEENABLE"},
339 {SC_RENDERSTATE, D3DRS_DEPTHBIAS, "D3DRS_DEPTHBIAS"},
340 {SC_RENDERSTATE, D3DRS_SEPARATEALPHABLENDENABLE, "D3DRS_SEPARATEALPHABLENDENABLE"},
341 {SC_RENDERSTATE, D3DRS_SRCBLENDALPHA, "D3DRS_SRCBLENDALPHA"},
342 {SC_RENDERSTATE, D3DRS_DESTBLENDALPHA, "D3DRS_DESTBLENDALPHA"},
343 {SC_RENDERSTATE, D3DRS_BLENDOPALPHA, "D3DRS_BLENDOPALPHA"},
344 /* Texture stages */
345 {SC_TEXTURESTAGE, D3DTSS_COLOROP, "D3DTSS_COLOROP"},
346 {SC_TEXTURESTAGE, D3DTSS_COLORARG0, "D3DTSS_COLORARG0"},
347 {SC_TEXTURESTAGE, D3DTSS_COLORARG1, "D3DTSS_COLORARG1"},
348 {SC_TEXTURESTAGE, D3DTSS_COLORARG2, "D3DTSS_COLORARG2"},
349 {SC_TEXTURESTAGE, D3DTSS_ALPHAOP, "D3DTSS_ALPHAOP"},
350 {SC_TEXTURESTAGE, D3DTSS_ALPHAARG0, "D3DTSS_ALPHAARG0"},
351 {SC_TEXTURESTAGE, D3DTSS_ALPHAARG1, "D3DTSS_ALPHAARG1"},
352 {SC_TEXTURESTAGE, D3DTSS_ALPHAARG2, "D3DTSS_ALPHAARG2"},
353 {SC_TEXTURESTAGE, D3DTSS_RESULTARG, "D3DTSS_RESULTARG"},
354 {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT00, "D3DTSS_BUMPENVMAT00"}, /* 0x70 */
355 {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT01, "D3DTSS_BUMPENVMAT01"},
356 {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT10, "D3DTSS_BUMPENVMAT10"},
357 {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT11, "D3DTSS_BUMPENVMAT11"},
358 {SC_TEXTURESTAGE, D3DTSS_TEXCOORDINDEX, "D3DTSS_TEXCOORDINDEX"},
359 {SC_TEXTURESTAGE, D3DTSS_BUMPENVLSCALE, "D3DTSS_BUMPENVLSCALE"},
360 {SC_TEXTURESTAGE, D3DTSS_BUMPENVLOFFSET, "D3DTSS_BUMPENVLOFFSET"},
361 {SC_TEXTURESTAGE, D3DTSS_TEXTURETRANSFORMFLAGS, "D3DTSS_TEXTURETRANSFORMFLAGS"},
362 {SC_TEXTURESTAGE, D3DTSS_CONSTANT, "D3DTSS_CONSTANT"},
363 /* NPatchMode */
364 {SC_NPATCHMODE, 0, "NPatchMode"},
365 /* FVF */
366 {SC_FVF, 0, "FVF"},
367 /* Transform */
368 {SC_TRANSFORM, D3DTS_PROJECTION, "D3DTS_PROJECTION"},
369 {SC_TRANSFORM, D3DTS_VIEW, "D3DTS_VIEW"},
370 {SC_TRANSFORM, D3DTS_WORLD, "D3DTS_WORLD"},
371 {SC_TRANSFORM, D3DTS_TEXTURE0, "D3DTS_TEXTURE0"},
372 /* Material */
373 {SC_MATERIAL, MT_DIFFUSE, "MaterialDiffuse"},
374 {SC_MATERIAL, MT_AMBIENT, "MaterialAmbient"}, /* 0x80 */
375 {SC_MATERIAL, MT_SPECULAR, "MaterialSpecular"},
376 {SC_MATERIAL, MT_EMISSIVE, "MaterialEmissive"},
377 {SC_MATERIAL, MT_POWER, "MaterialPower"},
378 /* Light */
379 {SC_LIGHT, LT_TYPE, "LightType"},
380 {SC_LIGHT, LT_DIFFUSE, "LightDiffuse"},
381 {SC_LIGHT, LT_SPECULAR, "LightSpecular"},
382 {SC_LIGHT, LT_AMBIENT, "LightAmbient"},
383 {SC_LIGHT, LT_POSITION, "LightPosition"},
384 {SC_LIGHT, LT_DIRECTION, "LightDirection"},
385 {SC_LIGHT, LT_RANGE, "LightRange"},
386 {SC_LIGHT, LT_FALLOFF, "LightFallOff"},
387 {SC_LIGHT, LT_ATTENUATION0, "LightAttenuation0"},
388 {SC_LIGHT, LT_ATTENUATION1, "LightAttenuation1"},
389 {SC_LIGHT, LT_ATTENUATION2, "LightAttenuation2"},
390 {SC_LIGHT, LT_THETA, "LightTheta"},
391 {SC_LIGHT, LT_PHI, "LightPhi"}, /* 0x90 */
392 /* Lightenable */
393 {SC_LIGHTENABLE, 0, "LightEnable"},
394 /* Vertexshader */
395 {SC_VERTEXSHADER, 0, "Vertexshader"},
396 /* Pixelshader */
397 {SC_PIXELSHADER, 0, "Pixelshader"},
398 /* Shader constants */
399 {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstantF"},
400 {SC_SHADERCONST, SCT_VSBOOL, "VertexShaderConstantB"},
401 {SC_SHADERCONST, SCT_VSINT, "VertexShaderConstantI"},
402 {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant"},
403 {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant1"},
404 {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant2"},
405 {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant3"},
406 {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant4"},
407 {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstantF"},
408 {SC_SHADERCONST, SCT_PSBOOL, "PixelShaderConstantB"},
409 {SC_SHADERCONST, SCT_PSINT, "PixelShaderConstantI"},
410 {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant"},
411 {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant1"}, /* 0xa0 */
412 {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant2"},
413 {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant3"},
414 {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant4"},
415 /* Texture */
416 {SC_TEXTURE, 0, "Texture"},
417 /* Sampler states */
418 {SC_SAMPLERSTATE, D3DSAMP_ADDRESSU, "AddressU"},
419 {SC_SAMPLERSTATE, D3DSAMP_ADDRESSV, "AddressV"},
420 {SC_SAMPLERSTATE, D3DSAMP_ADDRESSW, "AddressW"},
421 {SC_SAMPLERSTATE, D3DSAMP_BORDERCOLOR, "BorderColor"},
422 {SC_SAMPLERSTATE, D3DSAMP_MAGFILTER, "MagFilter"},
423 {SC_SAMPLERSTATE, D3DSAMP_MINFILTER, "MinFilter"},
424 {SC_SAMPLERSTATE, D3DSAMP_MIPFILTER, "MipFilter"},
425 {SC_SAMPLERSTATE, D3DSAMP_MIPMAPLODBIAS, "MipMapLodBias"},
426 {SC_SAMPLERSTATE, D3DSAMP_MAXMIPLEVEL, "MaxMipLevel"},
427 {SC_SAMPLERSTATE, D3DSAMP_MAXANISOTROPY, "MaxAnisotropy"},
428 {SC_SAMPLERSTATE, D3DSAMP_SRGBTEXTURE, "SRGBTexture"},
429 {SC_SAMPLERSTATE, D3DSAMP_ELEMENTINDEX, "ElementIndex"}, /* 0xb0 */
430 {SC_SAMPLERSTATE, D3DSAMP_DMAPOFFSET, "DMAPOffset"},
431 /* Set sampler */
432 {SC_SETSAMPLER, 0, "Sampler"},
435 static inline uint32_t read_u32(const char **ptr)
437 uint32_t u;
439 memcpy(&u, *ptr, sizeof(u));
440 *ptr += sizeof(u);
441 return u;
444 static void skip_u32_unknown(const char **ptr, unsigned int count)
446 unsigned int i;
447 uint32_t u;
449 WARN("Skipping %u unknown DWORDs:\n", count);
450 for (i = 0; i < count; ++i)
452 u = read_u32(ptr);
453 WARN("\t0x%08x\n", u);
457 static inline D3DXHANDLE get_parameter_handle(struct d3dx_parameter *parameter)
459 return (D3DXHANDLE)parameter;
462 static inline D3DXHANDLE get_technique_handle(struct d3dx_technique *technique)
464 return (D3DXHANDLE)technique;
467 static inline D3DXHANDLE get_pass_handle(struct d3dx_pass *pass)
469 return (D3DXHANDLE)pass;
472 static struct d3dx_technique *get_technique_by_name(struct d3dx_effect *effect, const char *name)
474 unsigned int i;
476 if (!name) return NULL;
478 for (i = 0; i < effect->technique_count; ++i)
480 if (!strcmp(effect->techniques[i].name, name))
481 return &effect->techniques[i];
484 return NULL;
487 static struct d3dx_technique *get_valid_technique(struct d3dx_effect *effect, D3DXHANDLE technique)
489 unsigned int i;
491 for (i = 0; i < effect->technique_count; ++i)
493 if (get_technique_handle(&effect->techniques[i]) == technique)
494 return &effect->techniques[i];
497 return get_technique_by_name(effect, technique);
500 static struct d3dx_pass *get_valid_pass(struct d3dx_effect *effect, D3DXHANDLE pass)
502 unsigned int i, k;
504 for (i = 0; i < effect->technique_count; ++i)
506 struct d3dx_technique *technique = &effect->techniques[i];
508 for (k = 0; k < technique->pass_count; ++k)
510 if (get_pass_handle(&technique->passes[k]) == pass)
511 return &technique->passes[k];
515 return NULL;
518 static struct d3dx_parameter *get_valid_parameter(struct d3dx_effect *effect, D3DXHANDLE parameter)
520 struct d3dx_parameter *handle_param = (struct d3dx_parameter *)parameter;
522 if (handle_param && !strncmp(handle_param->magic_string, parameter_magic_string,
523 sizeof(parameter_magic_string)))
524 return handle_param;
526 return effect->flags & D3DXFX_LARGEADDRESSAWARE ? NULL : get_parameter_by_name(&effect->params, NULL, parameter);
529 static struct d3dx_parameter_block *get_valid_parameter_block(D3DXHANDLE handle)
531 struct d3dx_parameter_block *block = (struct d3dx_parameter_block *)handle;
533 return block && !strncmp(block->magic_string, parameter_block_magic_string,
534 sizeof(parameter_block_magic_string)) ? block : NULL;
537 static void free_state(struct d3dx_state *state)
539 free_parameter(&state->parameter, FALSE, FALSE);
542 static void free_object(struct d3dx_object *object)
544 HeapFree(GetProcessHeap(), 0, object->data);
547 static void free_sampler(struct d3dx_sampler *sampler)
549 UINT i;
551 for (i = 0; i < sampler->state_count; ++i)
553 free_state(&sampler->states[i]);
555 heap_free(sampler->states);
558 static void d3dx_pool_release_shared_parameter(struct d3dx_top_level_parameter *param);
560 static void free_parameter_object_data(struct d3dx_parameter *param, const void *data, unsigned int bytes)
562 unsigned int i, count;
564 if (param->class != D3DXPC_OBJECT)
565 return;
567 count = min(param->element_count ? param->element_count : 1, bytes / sizeof(void *));
569 for (i = 0; i < count; ++i)
571 switch (param->type)
573 case D3DXPT_STRING:
574 heap_free(((char **)data)[i]);
575 break;
577 case D3DXPT_TEXTURE:
578 case D3DXPT_TEXTURE1D:
579 case D3DXPT_TEXTURE2D:
580 case D3DXPT_TEXTURE3D:
581 case D3DXPT_TEXTURECUBE:
582 case D3DXPT_PIXELSHADER:
583 case D3DXPT_VERTEXSHADER:
584 if (*(IUnknown **)data)
585 IUnknown_Release(((IUnknown **)data)[i]);
586 break;
588 case D3DXPT_SAMPLER:
589 case D3DXPT_SAMPLER1D:
590 case D3DXPT_SAMPLER2D:
591 case D3DXPT_SAMPLER3D:
592 case D3DXPT_SAMPLERCUBE:
593 assert(count == 1);
594 free_sampler((struct d3dx_sampler *)data);
595 return;
597 default:
598 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(param->type));
599 break;
604 static void free_parameter_data(struct d3dx_parameter *param, BOOL child)
606 if (!param->data)
607 return;
609 if (!param->element_count)
610 free_parameter_object_data(param, param->data, param->bytes);
612 if (!child || is_param_type_sampler(param->type))
613 heap_free(param->data);
616 static void free_parameter(struct d3dx_parameter *param, BOOL element, BOOL child)
618 unsigned int i;
620 TRACE("Free parameter %p, name %s, type %s, element %#x, child %#x.\n", param, param->name,
621 debug_d3dxparameter_type(param->type), element, child);
623 if (param->param_eval)
624 d3dx_free_param_eval(param->param_eval);
626 if (param->members)
628 unsigned int count = param->element_count ? param->element_count : param->member_count;
630 for (i = 0; i < count; ++i)
631 free_parameter(&param->members[i], param->element_count != 0, TRUE);
632 HeapFree(GetProcessHeap(), 0, param->members);
635 heap_free(param->full_name);
636 free_parameter_data(param, child);
638 /* only the parent has to release name and semantic */
639 if (!element)
641 HeapFree(GetProcessHeap(), 0, param->name);
642 HeapFree(GetProcessHeap(), 0, param->semantic);
646 static void free_top_level_parameter(struct d3dx_top_level_parameter *param)
648 if (param->annotations)
650 unsigned int i;
652 for (i = 0; i < param->annotation_count; ++i)
653 free_parameter(&param->annotations[i], FALSE, FALSE);
654 HeapFree(GetProcessHeap(), 0, param->annotations);
656 d3dx_pool_release_shared_parameter(param);
657 free_parameter(&param->param, FALSE, FALSE);
660 static void free_pass(struct d3dx_pass *pass)
662 unsigned int i;
664 TRACE("Free pass %p\n", pass);
666 if (!pass)
667 return;
669 if (pass->annotations)
671 for (i = 0; i < pass->annotation_count; ++i)
672 free_parameter(&pass->annotations[i], FALSE, FALSE);
673 HeapFree(GetProcessHeap(), 0, pass->annotations);
674 pass->annotations = NULL;
677 if (pass->states)
679 for (i = 0; i < pass->state_count; ++i)
680 free_state(&pass->states[i]);
681 HeapFree(GetProcessHeap(), 0, pass->states);
682 pass->states = NULL;
685 HeapFree(GetProcessHeap(), 0, pass->name);
686 pass->name = NULL;
689 static void free_technique(struct d3dx_technique *technique)
691 unsigned int i;
693 TRACE("Free technique %p\n", technique);
695 if (!technique)
696 return;
698 if (technique->saved_state)
700 IDirect3DStateBlock9_Release(technique->saved_state);
701 technique->saved_state = NULL;
704 if (technique->annotations)
706 for (i = 0; i < technique->annotation_count; ++i)
707 free_parameter(&technique->annotations[i], FALSE, FALSE);
708 HeapFree(GetProcessHeap(), 0, technique->annotations);
709 technique->annotations = NULL;
712 if (technique->passes)
714 for (i = 0; i < technique->pass_count; ++i)
715 free_pass(&technique->passes[i]);
716 HeapFree(GetProcessHeap(), 0, technique->passes);
717 technique->passes = NULL;
720 HeapFree(GetProcessHeap(), 0, technique->name);
721 technique->name = NULL;
724 static unsigned int get_recorded_parameter_size(const struct d3dx_recorded_parameter *record)
726 return sizeof(*record) + record->bytes;
729 static void free_parameter_block(struct d3dx_parameter_block *block)
731 struct d3dx_recorded_parameter *record;
733 if (!block)
734 return;
736 record = (struct d3dx_recorded_parameter *)block->buffer;
737 while ((BYTE *)record < block->buffer + block->offset)
739 free_parameter_object_data(record->param, record + 1, record->bytes);
740 record = (struct d3dx_recorded_parameter *)((BYTE *)record + get_recorded_parameter_size(record));
742 assert((BYTE *)record == block->buffer + block->offset);
744 heap_free(block->buffer);
745 heap_free(block);
748 static int param_rb_compare(const void *key, const struct wine_rb_entry *entry)
750 const char *name = key;
751 struct d3dx_parameter *param = WINE_RB_ENTRY_VALUE(entry, struct d3dx_parameter, rb_entry);
753 return strcmp(name, param->full_name);
756 HRESULT d3dx_init_parameters_store(struct d3dx_parameters_store *store, unsigned int count)
758 store->count = count;
759 wine_rb_init(&store->tree, param_rb_compare);
761 if (store->count && !(store->parameters = heap_alloc_zero(sizeof(*store->parameters) * store->count)))
762 return E_OUTOFMEMORY;
764 return S_OK;
767 void d3dx_parameters_store_cleanup(struct d3dx_parameters_store *store)
769 unsigned int i;
771 heap_free(store->full_name_tmp);
773 if (store->parameters)
775 for (i = 0; i < store->count; ++i)
776 free_top_level_parameter(&store->parameters[i]);
777 heap_free(store->parameters);
778 store->parameters = NULL;
782 static void d3dx_effect_cleanup(struct d3dx_effect *effect)
784 struct d3dx_parameter_block *block, *cursor;
785 ID3DXEffectPool *pool;
786 unsigned int i;
788 TRACE("effect %p.\n", effect);
790 free_parameter_block(effect->current_parameter_block);
791 LIST_FOR_EACH_ENTRY_SAFE(block, cursor, &effect->parameter_block_list, struct d3dx_parameter_block, entry)
793 list_remove(&block->entry);
794 free_parameter_block(block);
797 d3dx_parameters_store_cleanup(&effect->params);
799 if (effect->techniques)
801 for (i = 0; i < effect->technique_count; ++i)
802 free_technique(&effect->techniques[i]);
803 heap_free(effect->techniques);
806 if (effect->objects)
808 for (i = 0; i < effect->object_count; ++i)
809 free_object(&effect->objects[i]);
810 heap_free(effect->objects);
813 if (effect->pool)
815 pool = &effect->pool->ID3DXEffectPool_iface;
816 pool->lpVtbl->Release(pool);
819 if (effect->manager)
820 IUnknown_Release(effect->manager);
822 IDirect3DDevice9_Release(effect->device);
823 heap_free(effect);
826 static void get_vector(struct d3dx_parameter *param, D3DXVECTOR4 *vector)
828 UINT i;
830 for (i = 0; i < 4; ++i)
832 if (i < param->columns)
833 set_number((FLOAT *)vector + i, D3DXPT_FLOAT, (DWORD *)param->data + i, param->type);
834 else
835 ((FLOAT *)vector)[i] = 0.0f;
839 static void set_vector(struct d3dx_parameter *param, const D3DXVECTOR4 *vector, void *dst_data)
841 UINT i;
843 for (i = 0; i < param->columns; ++i)
844 set_number((FLOAT *)dst_data + i, param->type, (FLOAT *)vector + i, D3DXPT_FLOAT);
847 static void get_matrix(struct d3dx_parameter *param, D3DXMATRIX *matrix, BOOL transpose)
849 UINT i, k;
851 for (i = 0; i < 4; ++i)
853 for (k = 0; k < 4; ++k)
855 FLOAT *tmp = transpose ? (FLOAT *)&matrix->m[k][i] : (FLOAT *)&matrix->m[i][k];
857 if ((i < param->rows) && (k < param->columns))
858 set_number(tmp, D3DXPT_FLOAT, (DWORD *)param->data + i * param->columns + k, param->type);
859 else
860 *tmp = 0.0f;
865 static void set_matrix(struct d3dx_parameter *param, const D3DXMATRIX *matrix, void *dst_data)
867 UINT i, k;
869 if (param->type == D3DXPT_FLOAT)
871 if (param->columns == 4)
873 memcpy(dst_data, matrix->m, param->rows * 4 * sizeof(float));
875 else
877 for (i = 0; i < param->rows; ++i)
878 memcpy((float *)dst_data + i * param->columns, matrix->m + i, param->columns * sizeof(float));
880 return;
883 for (i = 0; i < param->rows; ++i)
885 for (k = 0; k < param->columns; ++k)
886 set_number((FLOAT *)dst_data + i * param->columns + k, param->type,
887 &matrix->m[i][k], D3DXPT_FLOAT);
891 static void set_matrix_transpose(struct d3dx_parameter *param, const D3DXMATRIX *matrix, void *dst_data)
893 UINT i, k;
895 for (i = 0; i < param->rows; ++i)
897 for (k = 0; k < param->columns; ++k)
899 set_number((FLOAT *)dst_data + i * param->columns + k, param->type,
900 &matrix->m[k][i], D3DXPT_FLOAT);
905 static HRESULT set_string(char **param_data, const char *string)
907 heap_free(*param_data);
908 *param_data = heap_alloc(strlen(string) + 1);
909 if (!*param_data)
911 ERR("Out of memory.\n");
912 return E_OUTOFMEMORY;
914 strcpy(*param_data, string);
915 return D3D_OK;
918 static HRESULT set_value(struct d3dx_parameter *param, const void *data, unsigned int bytes,
919 void *dst_data)
921 unsigned int i, count;
923 bytes = min(bytes, param->bytes);
924 count = min(param->element_count ? param->element_count : 1, bytes / sizeof(void *));
926 switch (param->type)
928 case D3DXPT_TEXTURE:
929 case D3DXPT_TEXTURE1D:
930 case D3DXPT_TEXTURE2D:
931 case D3DXPT_TEXTURE3D:
932 case D3DXPT_TEXTURECUBE:
933 for (i = 0; i < count; ++i)
935 IUnknown *old_texture = ((IUnknown **)dst_data)[i];
936 IUnknown *new_texture = ((IUnknown **)data)[i];
938 if (new_texture == old_texture)
939 continue;
941 if (new_texture)
942 IUnknown_AddRef(new_texture);
943 if (old_texture)
944 IUnknown_Release(old_texture);
946 /* fallthrough */
947 case D3DXPT_VOID:
948 case D3DXPT_BOOL:
949 case D3DXPT_INT:
950 case D3DXPT_FLOAT:
951 TRACE("Copy %u bytes.\n", bytes);
952 memcpy(dst_data, data, bytes);
953 break;
955 case D3DXPT_STRING:
957 HRESULT hr;
959 for (i = 0; i < count; ++i)
960 if (FAILED(hr = set_string(&((char **)dst_data)[i], ((const char **)data)[i])))
961 return hr;
962 break;
965 default:
966 FIXME("Unhandled type %s.\n", debug_d3dxparameter_type(param->type));
967 break;
970 return D3D_OK;
973 static struct d3dx_parameter *get_parameter_element_by_name(struct d3dx_parameters_store *store,
974 struct d3dx_parameter *parameter, const char *name)
976 UINT element;
977 struct d3dx_parameter *temp_parameter;
978 const char *part;
980 TRACE("parameter %p, name %s\n", parameter, debugstr_a(name));
982 if (!name || !*name) return NULL;
984 element = atoi(name);
985 part = strchr(name, ']') + 1;
987 /* check for empty [] && element range */
988 if ((part - name) > 1 && parameter->element_count > element)
990 temp_parameter = &parameter->members[element];
992 switch (*part++)
994 case '.':
995 return get_parameter_by_name(store, temp_parameter, part);
997 case '\0':
998 TRACE("Returning parameter %p\n", temp_parameter);
999 return temp_parameter;
1001 default:
1002 FIXME("Unhandled case \"%c\"\n", *--part);
1003 break;
1007 TRACE("Parameter not found\n");
1008 return NULL;
1011 static struct d3dx_parameter *get_annotation_by_name(struct d3dx_effect *effect, unsigned int count,
1012 struct d3dx_parameter *annotations, const char *name)
1014 UINT i, length;
1015 struct d3dx_parameter *temp_parameter;
1016 const char *part;
1018 TRACE("count %u, annotations %p, name %s\n", count, annotations, debugstr_a(name));
1020 if (!name || !*name) return NULL;
1022 length = strcspn( name, "[.@" );
1023 part = name + length;
1025 for (i = 0; i < count; ++i)
1027 temp_parameter = &annotations[i];
1029 if (!strcmp(temp_parameter->name, name))
1031 TRACE("Returning annotation %p\n", temp_parameter);
1032 return temp_parameter;
1034 else if (strlen(temp_parameter->name) == length && !strncmp(temp_parameter->name, name, length))
1036 switch (*part++)
1038 case '.':
1039 return get_parameter_by_name(&effect->params, temp_parameter, part);
1041 case '[':
1042 return get_parameter_element_by_name(&effect->params, temp_parameter, part);
1044 default:
1045 FIXME("Unhandled case \"%c\"\n", *--part);
1046 break;
1051 TRACE("Annotation not found\n");
1052 return NULL;
1055 struct d3dx_parameter *get_parameter_by_name(struct d3dx_parameters_store *store,
1056 struct d3dx_parameter *parameter, const char *name)
1058 struct d3dx_parameter *temp_parameter;
1059 unsigned int name_len, param_name_len;
1060 unsigned int i, count, length;
1061 struct wine_rb_entry *entry;
1062 unsigned int full_name_size;
1063 const char *part;
1064 char *full_name;
1066 TRACE("store %p, parameter %p, name %s.\n", store, parameter, debugstr_a(name));
1068 if (!name || !*name) return NULL;
1070 if (!parameter)
1072 if ((entry = wine_rb_get(&store->tree, name)))
1073 return WINE_RB_ENTRY_VALUE(entry, struct d3dx_parameter, rb_entry);
1074 return NULL;
1077 if (parameter->full_name)
1079 name_len = strlen(name);
1080 param_name_len = strlen(parameter->full_name);
1081 full_name_size = name_len + param_name_len + 2;
1082 if (store->full_name_tmp_size < full_name_size)
1084 if (!(full_name = heap_realloc(store->full_name_tmp, full_name_size)))
1086 ERR("Out of memory.\n");
1087 return NULL;
1089 store->full_name_tmp = full_name;
1090 store->full_name_tmp_size = full_name_size;
1092 else
1094 full_name = store->full_name_tmp;
1096 memcpy(full_name, parameter->full_name, param_name_len);
1097 full_name[param_name_len] = '.';
1098 memcpy(full_name + param_name_len + 1, name, name_len);
1099 full_name[param_name_len + 1 + name_len] = 0;
1101 if ((entry = wine_rb_get(&store->tree, full_name)))
1102 return WINE_RB_ENTRY_VALUE(entry, struct d3dx_parameter, rb_entry);
1103 return NULL;
1106 /* Pass / technique annotations are not stored in the parameters tree,
1107 * do a linear search. */
1108 count = parameter->member_count;
1110 length = strcspn( name, "[." );
1111 part = name + length;
1113 for (i = 0; i < count; i++)
1115 temp_parameter = &parameter->members[i];
1117 if (!strcmp(temp_parameter->name, name))
1119 TRACE("Returning parameter %p\n", temp_parameter);
1120 return temp_parameter;
1122 else if (strlen(temp_parameter->name) == length && !strncmp(temp_parameter->name, name, length))
1124 switch (*part++)
1126 case '.':
1127 return get_parameter_by_name(store, temp_parameter, part);
1129 case '[':
1130 return get_parameter_element_by_name(store, temp_parameter, part);
1132 default:
1133 FIXME("Unhandled case \"%c\"\n", *--part);
1134 break;
1139 TRACE("Parameter not found\n");
1140 return NULL;
1143 static inline DWORD d3dx9_effect_version(DWORD major, DWORD minor)
1145 return (0xfeff0000 | ((major) << 8) | (minor));
1148 static HRESULT d3dx9_get_param_value_ptr(struct d3dx_pass *pass, struct d3dx_state *state,
1149 void **param_value, struct d3dx_parameter **out_param,
1150 BOOL update_all, BOOL *param_dirty)
1152 struct d3dx_parameter *param = &state->parameter;
1154 *param_value = NULL;
1155 *out_param = NULL;
1156 *param_dirty = FALSE;
1158 switch (state->type)
1160 case ST_PARAMETER:
1161 param = state->referenced_param;
1162 *param_dirty = is_param_dirty(param, pass->update_version);
1163 /* fallthrough */
1164 case ST_CONSTANT:
1165 *out_param = param;
1166 *param_value = param->data;
1167 return D3D_OK;
1168 case ST_ARRAY_SELECTOR:
1170 unsigned int array_idx;
1171 static const struct d3dx_parameter array_idx_param =
1172 {"", NULL, NULL, NULL, NULL, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 0, 0, 0, sizeof(array_idx)};
1173 HRESULT hr;
1174 struct d3dx_parameter *ref_param, *selected_param;
1176 if (!param->param_eval)
1178 FIXME("Preshader structure is null.\n");
1179 return D3DERR_INVALIDCALL;
1181 /* We override with the update_version of the pass because we want
1182 * to force index recomputation and check for out of bounds. */
1183 if (is_param_eval_input_dirty(param->param_eval, pass->update_version))
1185 if (FAILED(hr = d3dx_evaluate_parameter(param->param_eval, &array_idx_param, &array_idx)))
1186 return hr;
1188 else
1190 array_idx = state->index;
1192 ref_param = state->referenced_param;
1193 TRACE("Array index %u, stored array index %u, element_count %u.\n", array_idx, state->index,
1194 ref_param->element_count);
1195 /* According to the tests, native d3dx handles the case of array index evaluated to -1
1196 * in a specific way, always selecting first array element and not returning error. */
1197 if (array_idx == ~0u)
1199 WARN("Array index is -1, setting to 0.\n");
1200 array_idx = 0;
1203 if (array_idx >= ref_param->element_count)
1205 WARN("Computed array index %u is larger than array size %u.\n",
1206 array_idx, ref_param->element_count);
1207 return E_FAIL;
1209 selected_param = &ref_param->members[array_idx];
1210 *param_dirty = state->index != array_idx || is_param_dirty(selected_param, pass->update_version);
1211 state->index = array_idx;
1213 *param_value = selected_param->data;
1214 *out_param = selected_param;
1215 return D3D_OK;
1217 case ST_FXLC:
1218 if (param->param_eval)
1220 *out_param = param;
1221 *param_value = param->data;
1222 /* We check with the update_version of the pass because the
1223 * same preshader might be used by both the vertex and the
1224 * pixel shader (that can happen e.g. for sampler states). */
1225 if (update_all || is_param_eval_input_dirty(param->param_eval, pass->update_version))
1227 *param_dirty = TRUE;
1228 return d3dx_evaluate_parameter(param->param_eval, param, *param_value);
1230 else
1231 return D3D_OK;
1233 else
1235 FIXME("No preshader for FXLC parameter.\n");
1236 return D3DERR_INVALIDCALL;
1239 return E_NOTIMPL;
1242 static unsigned int get_annotation_from_object(struct d3dx_effect *effect, D3DXHANDLE object,
1243 struct d3dx_parameter **annotations)
1245 struct d3dx_parameter *param = get_valid_parameter(effect, object);
1246 struct d3dx_pass *pass = get_valid_pass(effect, object);
1247 struct d3dx_technique *technique = get_valid_technique(effect, object);
1249 if (pass)
1251 *annotations = pass->annotations;
1252 return pass->annotation_count;
1254 else if (technique)
1256 *annotations = technique->annotations;
1257 return technique->annotation_count;
1259 else if (param)
1261 if (is_top_level_parameter(param))
1263 struct d3dx_top_level_parameter *top_param
1264 = top_level_parameter_from_parameter(param);
1266 *annotations = top_param->annotations;
1267 return top_param->annotation_count;
1269 else
1271 *annotations = NULL;
1272 return 0;
1275 else
1277 FIXME("Functions are not handled, yet!\n");
1278 return 0;
1282 static BOOL walk_parameter_tree(struct d3dx_parameter *param, walk_parameter_dep_func param_func,
1283 void *data)
1285 unsigned int i;
1286 unsigned int member_count;
1288 if (param_func(data, param))
1289 return TRUE;
1291 member_count = param->element_count ? param->element_count : param->member_count;
1292 for (i = 0; i < member_count; ++i)
1294 if (walk_parameter_tree(&param->members[i], param_func, data))
1295 return TRUE;
1297 return FALSE;
1300 static ULONG64 *get_version_counter_ptr(struct d3dx_effect *effect)
1302 return effect->pool ? &effect->pool->version_counter : &effect->version_counter;
1305 static ULONG64 next_effect_update_version(struct d3dx_effect *effect)
1307 return next_update_version(get_version_counter_ptr(effect));
1310 static void *record_parameter(struct d3dx_effect *effect, struct d3dx_parameter *param, unsigned int bytes)
1312 struct d3dx_parameter_block *block = effect->current_parameter_block;
1313 struct d3dx_recorded_parameter new_record, *record;
1314 unsigned int new_size, alloc_size;
1316 new_record.param = param;
1317 new_record.bytes = bytes;
1318 new_size = block->offset + get_recorded_parameter_size(&new_record);
1320 if (new_size > block->size)
1322 BYTE *new_alloc;
1324 alloc_size = max(block->size * 2, max(new_size, INITIAL_PARAM_BLOCK_SIZE));
1325 if (block->size)
1326 new_alloc = heap_realloc(block->buffer, alloc_size);
1327 else
1328 new_alloc = heap_alloc(alloc_size);
1330 if (!new_alloc)
1332 ERR("Out of memory.\n");
1333 return param->data;
1335 /* Data update functions may want to free some references upon setting value. */
1336 memset(new_alloc + block->size, 0, alloc_size - block->size);
1338 block->size = alloc_size;
1339 block->buffer = new_alloc;
1341 record = (struct d3dx_recorded_parameter *)(block->buffer + block->offset);
1342 *record = new_record;
1343 block->offset = new_size;
1344 return record + 1;
1347 static void set_dirty(struct d3dx_parameter *param)
1349 struct d3dx_top_level_parameter *top_param = param->top_level_param;
1350 struct d3dx_shared_data *shared_data;
1351 ULONG64 new_update_version;
1353 /* This is true for annotations. */
1354 if (!top_param)
1355 return;
1357 new_update_version = next_update_version(top_param->version_counter);
1358 if ((shared_data = top_param->shared_data))
1359 shared_data->update_version = new_update_version;
1360 else
1361 top_param->update_version = new_update_version;
1364 static void *param_get_data_and_dirtify(struct d3dx_effect *effect, struct d3dx_parameter *param,
1365 unsigned int bytes, BOOL value_changed)
1367 assert(bytes <= param->bytes);
1369 if (value_changed && !effect->current_parameter_block)
1370 set_dirty(param);
1372 return effect->current_parameter_block ? record_parameter(effect, param, bytes) : param->data;
1375 static void d3dx9_set_light_parameter(enum LIGHT_TYPE op, D3DLIGHT9 *light, void *value)
1377 static const struct
1379 unsigned int offset;
1380 const char *name;
1382 light_tbl[] =
1384 {FIELD_OFFSET(D3DLIGHT9, Type), "LC_TYPE"},
1385 {FIELD_OFFSET(D3DLIGHT9, Diffuse), "LT_DIFFUSE"},
1386 {FIELD_OFFSET(D3DLIGHT9, Specular), "LT_SPECULAR"},
1387 {FIELD_OFFSET(D3DLIGHT9, Ambient), "LT_AMBIENT"},
1388 {FIELD_OFFSET(D3DLIGHT9, Position), "LT_POSITION"},
1389 {FIELD_OFFSET(D3DLIGHT9, Direction), "LT_DIRECTION"},
1390 {FIELD_OFFSET(D3DLIGHT9, Range), "LT_RANGE"},
1391 {FIELD_OFFSET(D3DLIGHT9, Falloff), "LT_FALLOFF"},
1392 {FIELD_OFFSET(D3DLIGHT9, Attenuation0), "LT_ATTENUATION0"},
1393 {FIELD_OFFSET(D3DLIGHT9, Attenuation1), "LT_ATTENUATION1"},
1394 {FIELD_OFFSET(D3DLIGHT9, Attenuation2), "LT_ATTENUATION2"},
1395 {FIELD_OFFSET(D3DLIGHT9, Theta), "LT_THETA"},
1396 {FIELD_OFFSET(D3DLIGHT9, Phi), "LT_PHI"}
1398 switch (op)
1400 case LT_TYPE:
1401 TRACE("LT_TYPE %u.\n", *(D3DLIGHTTYPE *)value);
1402 light->Type = *(D3DLIGHTTYPE *)value;
1403 break;
1404 case LT_DIFFUSE:
1405 case LT_SPECULAR:
1406 case LT_AMBIENT:
1408 D3DCOLORVALUE c = *(D3DCOLORVALUE *)value;
1410 TRACE("%s (%.8e %.8e %.8e %.8e).\n", light_tbl[op].name, c.r, c.g, c.b, c.a);
1411 *(D3DCOLORVALUE *)((BYTE *)light + light_tbl[op].offset) = c;
1412 break;
1414 case LT_POSITION:
1415 case LT_DIRECTION:
1417 D3DVECTOR v = *(D3DVECTOR *)value;
1419 TRACE("%s (%.8e %.8e %.8e).\n", light_tbl[op].name, v.x, v.y, v.z);
1420 *(D3DVECTOR *)((BYTE *)light + light_tbl[op].offset) = v;
1421 break;
1423 case LT_RANGE:
1424 case LT_FALLOFF:
1425 case LT_ATTENUATION0:
1426 case LT_ATTENUATION1:
1427 case LT_ATTENUATION2:
1428 case LT_THETA:
1429 case LT_PHI:
1431 float v = *(float *)value;
1432 TRACE("%s %.8e.\n", light_tbl[op].name, v);
1433 *(float *)((BYTE *)light + light_tbl[op].offset) = v;
1434 break;
1436 default:
1437 WARN("Unknown light parameter %u.\n", op);
1438 break;
1442 static void d3dx9_set_material_parameter(enum MATERIAL_TYPE op, D3DMATERIAL9 *material, void *value)
1444 static const struct
1446 unsigned int offset;
1447 const char *name;
1449 material_tbl[] =
1451 {FIELD_OFFSET(D3DMATERIAL9, Diffuse), "MT_DIFFUSE"},
1452 {FIELD_OFFSET(D3DMATERIAL9, Ambient), "MT_AMBIENT"},
1453 {FIELD_OFFSET(D3DMATERIAL9, Specular), "MT_SPECULAR"},
1454 {FIELD_OFFSET(D3DMATERIAL9, Emissive), "MT_EMISSIVE"},
1455 {FIELD_OFFSET(D3DMATERIAL9, Power), "MT_POWER"}
1458 switch (op)
1460 case MT_POWER:
1462 float v = *(float *)value;
1464 TRACE("%s %.8e.\n", material_tbl[op].name, v);
1465 material->Power = v;
1466 break;
1468 case MT_DIFFUSE:
1469 case MT_AMBIENT:
1470 case MT_SPECULAR:
1471 case MT_EMISSIVE:
1473 D3DCOLORVALUE c = *(D3DCOLORVALUE *)value;
1475 TRACE("%s, value (%.8e %.8e %.8e %.8e).\n", material_tbl[op].name, c.r, c.g, c.b, c.a);
1476 *(D3DCOLORVALUE *)((BYTE *)material + material_tbl[op].offset) = c;
1477 break;
1479 default:
1480 WARN("Unknown material parameter %u.\n", op);
1481 break;
1485 static HRESULT d3dx_set_shader_const_state(struct d3dx_effect *effect, enum SHADER_CONSTANT_TYPE op, UINT index,
1486 struct d3dx_parameter *param, void *value_ptr)
1488 static const struct
1490 D3DXPARAMETER_TYPE type;
1491 UINT elem_size;
1492 const char *name;
1494 const_tbl[] =
1496 {D3DXPT_FLOAT, sizeof(float) * 4, "SCT_VSFLOAT"},
1497 {D3DXPT_BOOL, sizeof(BOOL), "SCT_VSBOOL"},
1498 {D3DXPT_INT, sizeof(int) * 4, "SCT_VSINT"},
1499 {D3DXPT_FLOAT, sizeof(float) * 4, "SCT_PSFLOAT"},
1500 {D3DXPT_BOOL, sizeof(BOOL), "SCT_PSBOOL"},
1501 {D3DXPT_INT, sizeof(int) * 4, "SCT_PSINT"},
1504 BOOL is_heap_buffer = FALSE;
1505 unsigned int element_count;
1506 void *buffer = value_ptr;
1507 D3DXVECTOR4 value;
1508 HRESULT ret;
1510 assert(op < ARRAY_SIZE(const_tbl));
1511 element_count = param->bytes / const_tbl[op].elem_size;
1512 TRACE("%s, index %u, element_count %u.\n", const_tbl[op].name, index, element_count);
1513 if (param->type != const_tbl[op].type)
1515 FIXME("Unexpected param type %u.\n", param->type);
1516 return D3DERR_INVALIDCALL;
1519 if (param->bytes % const_tbl[op].elem_size || element_count > 1)
1521 unsigned int param_data_size;
1523 TRACE("Parameter size %u, rows %u, cols %u.\n", param->bytes, param->rows, param->columns);
1525 if (param->bytes % const_tbl[op].elem_size)
1526 ++element_count;
1527 if (element_count > 1)
1529 WARN("Setting %u elements.\n", element_count);
1530 buffer = HeapAlloc(GetProcessHeap(), 0, const_tbl[op].elem_size * element_count);
1531 if (!buffer)
1533 ERR("Out of memory.\n");
1534 return E_OUTOFMEMORY;
1536 is_heap_buffer = TRUE;
1538 else
1540 assert(const_tbl[op].elem_size <= sizeof(value));
1541 buffer = &value;
1543 param_data_size = min(param->bytes, const_tbl[op].elem_size);
1544 memcpy(buffer, value_ptr, param_data_size);
1545 memset((unsigned char *)buffer + param_data_size, 0,
1546 const_tbl[op].elem_size * element_count - param_data_size);
1549 switch (op)
1551 case SCT_VSFLOAT:
1552 ret = SET_D3D_STATE(effect, SetVertexShaderConstantF, index, (const float *)buffer, element_count);
1553 break;
1554 case SCT_VSBOOL:
1555 ret = SET_D3D_STATE(effect, SetVertexShaderConstantB, index, (const BOOL *)buffer, element_count);
1556 break;
1557 case SCT_VSINT:
1558 ret = SET_D3D_STATE(effect, SetVertexShaderConstantI, index, (const int *)buffer, element_count);
1559 break;
1560 case SCT_PSFLOAT:
1561 ret = SET_D3D_STATE(effect, SetPixelShaderConstantF, index, (const float *)buffer, element_count);
1562 break;
1563 case SCT_PSBOOL:
1564 ret = SET_D3D_STATE(effect, SetPixelShaderConstantB, index, (const BOOL *)buffer, element_count);
1565 break;
1566 case SCT_PSINT:
1567 ret = SET_D3D_STATE(effect, SetPixelShaderConstantI, index, (const int *)buffer, element_count);
1568 break;
1569 default:
1570 ret = D3DERR_INVALIDCALL;
1571 break;
1574 if (is_heap_buffer)
1575 HeapFree(GetProcessHeap(), 0, buffer);
1577 return ret;
1580 static HRESULT d3dx9_apply_state(struct d3dx_effect *effect, struct d3dx_pass *pass,
1581 struct d3dx_state *state, unsigned int parent_index, BOOL update_all);
1583 static HRESULT d3dx_set_shader_constants(struct d3dx_effect *effect, struct d3dx_pass *pass,
1584 struct d3dx_parameter *param, BOOL vs, BOOL update_all)
1586 HRESULT hr, ret;
1587 struct d3dx_parameter **params;
1588 D3DXCONSTANT_DESC *cdesc;
1589 unsigned int parameters_count;
1590 unsigned int i, j;
1592 if (!param->param_eval)
1594 FIXME("param_eval structure is null.\n");
1595 return D3DERR_INVALIDCALL;
1597 if (FAILED(hr = d3dx_param_eval_set_shader_constants(effect->manager, effect->device,
1598 param->param_eval, update_all)))
1599 return hr;
1600 params = param->param_eval->shader_inputs.inputs_param;
1601 cdesc = param->param_eval->shader_inputs.inputs;
1602 parameters_count = param->param_eval->shader_inputs.input_count;
1603 ret = D3D_OK;
1604 for (i = 0; i < parameters_count; ++i)
1606 if (params[i] && params[i]->class == D3DXPC_OBJECT && is_param_type_sampler(params[i]->type))
1608 struct d3dx_sampler *sampler;
1609 unsigned int sampler_idx;
1611 for (sampler_idx = 0; sampler_idx < cdesc[i].RegisterCount; ++sampler_idx)
1613 sampler = params[i]->element_count ? params[i]->members[sampler_idx].data : params[i]->data;
1614 TRACE("sampler %s, register index %u, state count %u.\n", debugstr_a(params[i]->name),
1615 cdesc[i].RegisterIndex, sampler->state_count);
1616 for (j = 0; j < sampler->state_count; ++j)
1618 if (FAILED(hr = d3dx9_apply_state(effect, pass, &sampler->states[j],
1619 cdesc[i].RegisterIndex + sampler_idx + (vs ? D3DVERTEXTEXTURESAMPLER0 : 0),
1620 update_all)))
1621 ret = hr;
1626 return ret;
1629 static HRESULT d3dx9_apply_state(struct d3dx_effect *effect, struct d3dx_pass *pass,
1630 struct d3dx_state *state, unsigned int parent_index, BOOL update_all)
1632 struct d3dx_parameter *param;
1633 void *param_value;
1634 BOOL param_dirty;
1635 HRESULT hr;
1637 TRACE("operation %u, index %u, type %u.\n", state->operation, state->index, state->type);
1639 if (FAILED(hr = d3dx9_get_param_value_ptr(pass, state, &param_value, &param,
1640 update_all, &param_dirty)))
1642 if (!update_all && hr == E_FAIL)
1644 /* Native d3dx9 returns D3D_OK from CommitChanges() involving
1645 * out of bounds array access and does not touch the affected
1646 * states. */
1647 WARN("Returning D3D_OK on out of bounds array access.\n");
1648 return D3D_OK;
1650 return hr;
1653 if (!(update_all || param_dirty
1654 || state_table[state->operation].class == SC_VERTEXSHADER
1655 || state_table[state->operation].class == SC_PIXELSHADER
1656 || state_table[state->operation].class == SC_SETSAMPLER))
1657 return D3D_OK;
1659 switch (state_table[state->operation].class)
1661 case SC_RENDERSTATE:
1662 TRACE("%s, operation %u, value %lu.\n", state_table[state->operation].name,
1663 state_table[state->operation].op, *(DWORD *)param_value);
1664 return SET_D3D_STATE(effect, SetRenderState, state_table[state->operation].op, *(DWORD *)param_value);
1665 case SC_FVF:
1666 TRACE("%s, value %#lx.\n", state_table[state->operation].name, *(DWORD *)param_value);
1667 return SET_D3D_STATE(effect, SetFVF, *(DWORD *)param_value);
1668 case SC_TEXTURE:
1670 UINT unit;
1672 unit = parent_index == ~0u ? state->index : parent_index;
1673 TRACE("%s, unit %u, value %p.\n", state_table[state->operation].name, unit,
1674 *(IDirect3DBaseTexture9 **)param_value);
1675 return SET_D3D_STATE(effect, SetTexture, unit, *(IDirect3DBaseTexture9 **)param_value);
1677 case SC_TEXTURESTAGE:
1678 TRACE("%s, stage %u, value %lu.\n", state_table[state->operation].name, state->index, *(DWORD *)param_value);
1679 return SET_D3D_STATE(effect, SetTextureStageState, state->index,
1680 state_table[state->operation].op, *(DWORD *)param_value);
1681 case SC_SETSAMPLER:
1683 struct d3dx_sampler *sampler;
1684 HRESULT ret, hr;
1685 unsigned int i;
1687 sampler = (struct d3dx_sampler *)param_value;
1688 TRACE("%s, sampler %u, applying %u states.\n", state_table[state->operation].name, state->index,
1689 sampler->state_count);
1690 ret = D3D_OK;
1691 for (i = 0; i < sampler->state_count; i++)
1693 if (FAILED(hr = d3dx9_apply_state(effect, pass, &sampler->states[i], state->index, update_all)))
1694 ret = hr;
1696 return ret;
1698 case SC_SAMPLERSTATE:
1700 UINT sampler;
1702 sampler = parent_index == ~0u ? state->index : parent_index;
1703 TRACE("%s, sampler %u, value %lu.\n", state_table[state->operation].name, sampler, *(DWORD *)param_value);
1704 return SET_D3D_STATE(effect, SetSamplerState, sampler, state_table[state->operation].op,
1705 *(DWORD *)param_value);
1707 case SC_VERTEXSHADER:
1708 TRACE("%s, shader %p.\n", state_table[state->operation].name, *(IDirect3DVertexShader9 **)param_value);
1709 if ((update_all || param_dirty)
1710 && FAILED(hr = SET_D3D_STATE(effect, SetVertexShader,
1711 *(IDirect3DVertexShader9 **)param_value)))
1712 ERR("Could not set vertex shader, hr %#lx.\n", hr);
1713 else if (*(IDirect3DVertexShader9 **)param_value)
1714 hr = d3dx_set_shader_constants(effect, pass, param, TRUE, update_all || param_dirty);
1715 return hr;
1716 case SC_PIXELSHADER:
1717 TRACE("%s, shader %p.\n", state_table[state->operation].name, *(IDirect3DPixelShader9 **)param_value);
1718 if ((update_all || param_dirty)
1719 && FAILED(hr = SET_D3D_STATE(effect, SetPixelShader,
1720 *(IDirect3DPixelShader9 **)param_value)))
1721 ERR("Could not set pixel shader, hr %#lx.\n", hr);
1722 else if (*(IDirect3DPixelShader9 **)param_value)
1723 hr = d3dx_set_shader_constants(effect, pass, param, FALSE, update_all || param_dirty);
1724 return hr;
1725 case SC_TRANSFORM:
1726 TRACE("%s, state %u.\n", state_table[state->operation].name, state->index);
1727 return SET_D3D_STATE(effect, SetTransform, state_table[state->operation].op + state->index,
1728 (D3DMATRIX *)param_value);
1729 case SC_LIGHTENABLE:
1730 TRACE("%s, index %u, value %u.\n", state_table[state->operation].name, state->index, *(BOOL *)param_value);
1731 return SET_D3D_STATE(effect, LightEnable, state->index, *(BOOL *)param_value);
1732 case SC_LIGHT:
1734 TRACE("%s, index %u, op %u.\n", state_table[state->operation].name, state->index,
1735 state_table[state->operation].op);
1736 d3dx9_set_light_parameter(state_table[state->operation].op,
1737 &effect->current_light[state->index], param_value);
1738 effect->light_updated |= 1u << state->index;
1739 return D3D_OK;
1741 case SC_MATERIAL:
1743 TRACE("%s, index %u, op %u.\n", state_table[state->operation].name, state->index,
1744 state_table[state->operation].op);
1745 d3dx9_set_material_parameter(state_table[state->operation].op,
1746 &effect->current_material, param_value);
1747 effect->material_updated = TRUE;
1748 return D3D_OK;
1750 case SC_NPATCHMODE:
1751 TRACE("%s, nsegments %f.\n", state_table[state->operation].name, *(float *)param_value);
1752 return SET_D3D_STATE(effect, SetNPatchMode, *(float *)param_value);
1753 case SC_SHADERCONST:
1754 TRACE("%s, index %u, op %u.\n", state_table[state->operation].name, state->index,
1755 state_table[state->operation].op);
1756 return d3dx_set_shader_const_state(effect, state_table[state->operation].op, state->index,
1757 param, param_value);
1758 default:
1759 FIXME("%s not handled.\n", state_table[state->operation].name);
1760 break;
1762 return D3D_OK;
1765 static HRESULT d3dx9_apply_pass_states(struct d3dx_effect *effect, struct d3dx_pass *pass, BOOL update_all)
1767 unsigned int i;
1768 HRESULT ret;
1769 HRESULT hr;
1770 ULONG64 new_update_version = next_effect_update_version(effect);
1772 TRACE("effect %p, pass %p, state_count %u.\n", effect, pass, pass->state_count);
1774 ret = D3D_OK;
1775 for (i = 0; i < pass->state_count; ++i)
1777 if (FAILED(hr = d3dx9_apply_state(effect, pass, &pass->states[i], ~0u, update_all)))
1779 WARN("Error applying state, hr %#lx.\n", hr);
1780 ret = hr;
1784 if (effect->light_updated)
1786 for (i = 0; i < ARRAY_SIZE(effect->current_light); ++i)
1788 if ((effect->light_updated & (1u << i))
1789 && FAILED(hr = SET_D3D_STATE(effect, SetLight, i, &effect->current_light[i])))
1791 WARN("Error setting light, hr %#lx.\n", hr);
1792 ret = hr;
1795 effect->light_updated = 0;
1798 if (effect->material_updated
1799 && FAILED(hr = SET_D3D_STATE(effect, SetMaterial, &effect->current_material)))
1801 WARN("Error setting material, hr %#lx.\n", hr);
1802 ret = hr;
1804 effect->material_updated = FALSE;
1806 pass->update_version = new_update_version;
1807 return ret;
1810 static void param_set_data_pointer(struct d3dx_parameter *param, unsigned char *data, BOOL child, BOOL free_data)
1812 unsigned char *member_data = data;
1813 unsigned int i, count;
1815 count = param->element_count ? param->element_count : param->member_count;
1816 for (i = 0; i < count; ++i)
1818 param_set_data_pointer(&param->members[i], member_data, TRUE, free_data);
1819 if (data)
1820 member_data += param->members[i].bytes;
1822 if (free_data)
1823 free_parameter_data(param, child);
1824 param->data = data;
1827 static BOOL is_same_parameter(void *param1_, struct d3dx_parameter *param2)
1829 struct d3dx_parameter *param1 = (struct d3dx_parameter *)param1_;
1830 BOOL matches;
1831 unsigned int i, member_count;
1833 matches = !strcmp(param1->name, param2->name) && param1->class == param2->class
1834 && param1->type == param2->type && param1->rows == param2->rows
1835 && param1->columns == param2->columns && param1->element_count == param2->element_count
1836 && param1->member_count == param2->member_count;
1838 member_count = param1->element_count ? param1->element_count : param1->member_count;
1840 if (!matches || !member_count)
1841 return matches;
1843 for (i = 0; i < member_count; ++i)
1845 if (!is_same_parameter(&param1->members[i], &param2->members[i]))
1846 return FALSE;
1848 return TRUE;
1851 static HRESULT d3dx_pool_sync_shared_parameter(struct d3dx_effect_pool *pool, struct d3dx_top_level_parameter *param)
1853 unsigned int i, free_entry_index;
1854 unsigned int new_size, new_count;
1856 if (!(param->param.flags & PARAMETER_FLAG_SHARED) || !pool || is_param_type_sampler(param->param.type))
1857 return D3D_OK;
1859 free_entry_index = pool->size;
1860 for (i = 0; i < pool->size; ++i)
1862 if (!pool->shared_data[i].count)
1863 free_entry_index = i;
1864 else if (is_same_parameter(&param->param, &pool->shared_data[i].parameters[0]->param))
1865 break;
1867 if (i == pool->size)
1869 i = free_entry_index;
1870 if (i == pool->size)
1872 struct d3dx_shared_data *new_alloc;
1874 if (!pool->size)
1876 new_size = INITIAL_POOL_SIZE;
1877 new_alloc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1878 sizeof(*pool->shared_data) * new_size);
1879 if (!new_alloc)
1881 ERR("Out of memory.\n");
1882 return E_OUTOFMEMORY;
1885 else
1887 new_size = pool->size * 2;
1888 new_alloc = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pool->shared_data,
1889 sizeof(*pool->shared_data) * new_size);
1890 if (!new_alloc)
1892 ERR("Out of memory.\n");
1893 return E_OUTOFMEMORY;
1895 if (new_alloc != pool->shared_data)
1897 unsigned int j, k;
1899 for (j = 0; j < pool->size; ++j)
1900 for (k = 0; k < new_alloc[j].count; ++k)
1901 new_alloc[j].parameters[k]->shared_data = &new_alloc[j];
1904 pool->shared_data = new_alloc;
1905 pool->size = new_size;
1907 pool->shared_data[i].data = param->param.data;
1909 else
1911 param_set_data_pointer(&param->param, pool->shared_data[i].data, FALSE, TRUE);
1913 new_count = ++pool->shared_data[i].count;
1914 if (new_count >= pool->shared_data[i].size)
1916 if (!pool->shared_data[i].size)
1918 new_size = INITIAL_SHARED_DATA_SIZE;
1919 pool->shared_data[i].parameters = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1920 sizeof(*pool->shared_data[i].parameters) * INITIAL_SHARED_DATA_SIZE);
1922 else
1924 new_size = pool->shared_data[i].size * 2;
1925 pool->shared_data[i].parameters = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1926 pool->shared_data[i].parameters,
1927 sizeof(*pool->shared_data[i].parameters) * new_size);
1929 pool->shared_data[i].size = new_size;
1932 param->shared_data = &pool->shared_data[i];
1933 pool->shared_data[i].parameters[new_count - 1] = param;
1935 TRACE("name %s, parameter idx %u, new refcount %u.\n", debugstr_a(param->param.name), i,
1936 new_count);
1938 return D3D_OK;
1941 static BOOL param_zero_data_func(void *dummy, struct d3dx_parameter *param)
1943 param->data = NULL;
1944 return FALSE;
1947 static void d3dx_pool_release_shared_parameter(struct d3dx_top_level_parameter *param)
1949 unsigned int new_count;
1951 if (!(param->param.flags & PARAMETER_FLAG_SHARED) || !param->shared_data)
1952 return;
1953 new_count = --param->shared_data->count;
1955 TRACE("param %p, param->shared_data %p, new_count %d.\n", param, param->shared_data, new_count);
1957 if (new_count)
1959 unsigned int i;
1961 for (i = 0; i < new_count; ++i)
1963 if (param->shared_data->parameters[i] == param)
1965 memmove(&param->shared_data->parameters[i],
1966 &param->shared_data->parameters[i + 1],
1967 sizeof(param->shared_data->parameters[i]) * (new_count - i));
1968 break;
1971 walk_parameter_tree(&param->param, param_zero_data_func, NULL);
1973 else
1975 HeapFree(GetProcessHeap(), 0, param->shared_data->parameters);
1976 /* Zeroing table size is required as the entry in pool parameters table can be reused. */
1977 param->shared_data->size = 0;
1978 param->shared_data = NULL;
1982 static inline struct d3dx_effect_pool *impl_from_ID3DXEffectPool(ID3DXEffectPool *iface)
1984 return CONTAINING_RECORD(iface, struct d3dx_effect_pool, ID3DXEffectPool_iface);
1987 static inline struct d3dx_effect_pool *unsafe_impl_from_ID3DXEffectPool(ID3DXEffectPool *iface);
1989 static inline struct d3dx_effect *impl_from_ID3DXEffect(ID3DXEffect *iface)
1991 return CONTAINING_RECORD(iface, struct d3dx_effect, ID3DXEffect_iface);
1994 /*** IUnknown methods ***/
1995 static HRESULT WINAPI d3dx_effect_QueryInterface(ID3DXEffect *iface, REFIID riid, void **object)
1997 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), object);
1999 if (IsEqualGUID(riid, &IID_IUnknown) ||
2000 IsEqualGUID(riid, &IID_ID3DXEffect))
2002 iface->lpVtbl->AddRef(iface);
2003 *object = iface;
2004 return S_OK;
2007 ERR("Interface %s not found\n", debugstr_guid(riid));
2009 return E_NOINTERFACE;
2012 static ULONG WINAPI d3dx_effect_AddRef(ID3DXEffect *iface)
2014 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2015 ULONG refcount = InterlockedIncrement(&effect->ref);
2017 TRACE("%p increasing refcount to %lu.\n", effect, refcount);
2019 return refcount;
2022 static ULONG WINAPI d3dx_effect_Release(ID3DXEffect *iface)
2024 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2025 ULONG refcount = InterlockedDecrement(&effect->ref);
2027 TRACE("%p decreasing refcount to %lu.\n", effect, refcount);
2029 if (!refcount)
2030 d3dx_effect_cleanup(effect);
2032 return refcount;
2035 /*** ID3DXBaseEffect methods ***/
2036 static HRESULT WINAPI d3dx_effect_GetDesc(ID3DXEffect *iface, D3DXEFFECT_DESC *desc)
2038 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2040 FIXME("iface %p, desc %p partial stub.\n", iface, desc);
2042 if (!desc)
2044 WARN("Invalid argument specified.\n");
2045 return D3DERR_INVALIDCALL;
2048 /* TODO: add creator and function count. */
2049 desc->Creator = NULL;
2050 desc->Functions = 0;
2051 desc->Parameters = effect->params.count;
2052 desc->Techniques = effect->technique_count;
2054 return D3D_OK;
2057 static HRESULT WINAPI d3dx_effect_GetParameterDesc(ID3DXEffect *iface, D3DXHANDLE parameter,
2058 D3DXPARAMETER_DESC *desc)
2060 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2061 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2063 TRACE("iface %p, parameter %p, desc %p.\n", iface, parameter, desc);
2065 if (!desc || !param)
2067 WARN("Invalid argument specified.\n");
2068 return D3DERR_INVALIDCALL;
2071 desc->Name = param->name;
2072 desc->Semantic = param->semantic;
2073 desc->Class = param->class;
2074 desc->Type = param->type;
2075 desc->Rows = param->rows;
2076 desc->Columns = param->columns;
2077 desc->Elements = param->element_count;
2078 desc->Annotations = is_top_level_parameter(param)
2079 ? top_level_parameter_from_parameter(param)->annotation_count : 0;
2080 desc->StructMembers = param->member_count;
2081 desc->Flags = param->flags;
2082 desc->Bytes = param->bytes;
2084 return D3D_OK;
2087 static HRESULT WINAPI d3dx_effect_GetTechniqueDesc(ID3DXEffect *iface, D3DXHANDLE technique,
2088 D3DXTECHNIQUE_DESC *desc)
2090 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2091 struct d3dx_technique *tech = technique ? get_valid_technique(effect, technique) : &effect->techniques[0];
2093 TRACE("iface %p, technique %p, desc %p.\n", iface, technique, desc);
2095 if (!desc || !tech)
2097 WARN("Invalid argument specified.\n");
2098 return D3DERR_INVALIDCALL;
2101 desc->Name = tech->name;
2102 desc->Passes = tech->pass_count;
2103 desc->Annotations = tech->annotation_count;
2105 return D3D_OK;
2108 static HRESULT WINAPI d3dx_effect_GetPassDesc(ID3DXEffect *iface, D3DXHANDLE pass_handle, D3DXPASS_DESC *desc)
2110 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2111 struct d3dx_pass *pass = get_valid_pass(effect, pass_handle);
2112 unsigned int i;
2114 TRACE("iface %p, pass %p, desc %p.\n", iface, pass, desc);
2116 if (!desc || !pass)
2118 WARN("Invalid argument specified.\n");
2119 return D3DERR_INVALIDCALL;
2122 desc->Name = pass->name;
2123 desc->Annotations = pass->annotation_count;
2125 desc->pVertexShaderFunction = NULL;
2126 desc->pPixelShaderFunction = NULL;
2128 if (effect->flags & D3DXFX_NOT_CLONEABLE)
2129 return D3D_OK;
2131 for (i = 0; i < pass->state_count; ++i)
2133 struct d3dx_state *state = &pass->states[i];
2135 if (state_table[state->operation].class == SC_VERTEXSHADER
2136 || state_table[state->operation].class == SC_PIXELSHADER)
2138 struct d3dx_parameter *param;
2139 void *param_value;
2140 BOOL param_dirty;
2141 HRESULT hr;
2142 void *data;
2144 if (FAILED(hr = d3dx9_get_param_value_ptr(pass, &pass->states[i], &param_value, &param,
2145 FALSE, &param_dirty)))
2146 return hr;
2148 data = param->object_id ? effect->objects[param->object_id].data : NULL;
2149 if (state_table[state->operation].class == SC_VERTEXSHADER)
2150 desc->pVertexShaderFunction = data;
2151 else
2152 desc->pPixelShaderFunction = data;
2156 return D3D_OK;
2159 static HRESULT WINAPI d3dx_effect_GetFunctionDesc(ID3DXEffect *iface, D3DXHANDLE shader,
2160 D3DXFUNCTION_DESC *desc)
2162 FIXME("iface %p, shader %p, desc %p stub.\n", iface, shader, desc);
2164 return E_NOTIMPL;
2167 static D3DXHANDLE WINAPI d3dx_effect_GetParameter(ID3DXEffect *iface, D3DXHANDLE parameter, UINT index)
2169 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2170 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2172 TRACE("iface %p, parameter %p, index %u.\n", iface, parameter, index);
2174 if (!parameter)
2176 if (index < effect->params.count)
2178 TRACE("Returning parameter %p.\n", &effect->params.parameters[index]);
2179 return get_parameter_handle(&effect->params.parameters[index].param);
2182 else
2184 if (param && !param->element_count && index < param->member_count)
2186 TRACE("Returning parameter %p.\n", &param->members[index]);
2187 return get_parameter_handle(&param->members[index]);
2191 WARN("Parameter not found.\n");
2193 return NULL;
2196 static D3DXHANDLE WINAPI d3dx_effect_GetParameterByName(ID3DXEffect *iface, D3DXHANDLE parameter,
2197 const char *name)
2199 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2200 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2201 D3DXHANDLE handle;
2203 TRACE("iface %p, parameter %p, name %s.\n", iface, parameter, debugstr_a(name));
2205 if (!name)
2207 handle = get_parameter_handle(param);
2208 TRACE("Returning parameter %p.\n", handle);
2209 return handle;
2212 handle = get_parameter_handle(get_parameter_by_name(&effect->params, param, name));
2213 TRACE("Returning parameter %p.\n", handle);
2215 return handle;
2218 static D3DXHANDLE WINAPI d3dx_effect_GetParameterBySemantic(ID3DXEffect *iface, D3DXHANDLE parameter,
2219 const char *semantic)
2221 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2222 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2223 struct d3dx_parameter *temp_param;
2224 unsigned int i;
2226 TRACE("iface %p, parameter %p, semantic %s.\n", iface, parameter, debugstr_a(semantic));
2228 if (!parameter)
2230 for (i = 0; i < effect->params.count; ++i)
2232 temp_param = &effect->params.parameters[i].param;
2234 if (!temp_param->semantic)
2236 if (!semantic)
2238 TRACE("Returning parameter %p\n", temp_param);
2239 return get_parameter_handle(temp_param);
2241 continue;
2244 if (!stricmp(temp_param->semantic, semantic))
2246 TRACE("Returning parameter %p\n", temp_param);
2247 return get_parameter_handle(temp_param);
2251 else if (param)
2253 for (i = 0; i < param->member_count; ++i)
2255 temp_param = &param->members[i];
2257 if (!temp_param->semantic)
2259 if (!semantic)
2261 TRACE("Returning parameter %p\n", temp_param);
2262 return get_parameter_handle(temp_param);
2264 continue;
2267 if (!stricmp(temp_param->semantic, semantic))
2269 TRACE("Returning parameter %p\n", temp_param);
2270 return get_parameter_handle(temp_param);
2275 WARN("Parameter not found.\n");
2277 return NULL;
2280 static D3DXHANDLE WINAPI d3dx_effect_GetParameterElement(ID3DXEffect *iface, D3DXHANDLE parameter, UINT index)
2282 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2283 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2285 TRACE("iface %p, parameter %p, index %u.\n", iface, parameter, index);
2287 if (!param)
2289 if (index < effect->params.count)
2291 TRACE("Returning parameter %p.\n", &effect->params.parameters[index]);
2292 return get_parameter_handle(&effect->params.parameters[index].param);
2295 else
2297 if (index < param->element_count)
2299 TRACE("Returning parameter %p.\n", &param->members[index]);
2300 return get_parameter_handle(&param->members[index]);
2304 WARN("Parameter not found.\n");
2306 return NULL;
2309 static D3DXHANDLE WINAPI d3dx_effect_GetTechnique(ID3DXEffect *iface, UINT index)
2311 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2313 TRACE("iface %p, index %u.\n", iface, index);
2315 if (index >= effect->technique_count)
2317 WARN("Invalid argument specified.\n");
2318 return NULL;
2321 TRACE("Returning technique %p.\n", &effect->techniques[index]);
2323 return get_technique_handle(&effect->techniques[index]);
2326 static D3DXHANDLE WINAPI d3dx_effect_GetTechniqueByName(ID3DXEffect *iface, const char *name)
2328 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2329 struct d3dx_technique *tech = get_technique_by_name(effect, name);
2331 TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
2333 if (tech)
2335 D3DXHANDLE t = get_technique_handle(tech);
2336 TRACE("Returning technique %p\n", t);
2337 return t;
2340 WARN("Technique not found.\n");
2342 return NULL;
2345 static D3DXHANDLE WINAPI d3dx_effect_GetPass(ID3DXEffect *iface, D3DXHANDLE technique, UINT index)
2347 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2348 struct d3dx_technique *tech = get_valid_technique(effect, technique);
2350 TRACE("iface %p, technique %p, index %u.\n", iface, technique, index);
2352 if (tech && index < tech->pass_count)
2354 TRACE("Returning pass %p\n", &tech->passes[index]);
2355 return get_pass_handle(&tech->passes[index]);
2358 WARN("Pass not found.\n");
2360 return NULL;
2363 static D3DXHANDLE WINAPI d3dx_effect_GetPassByName(ID3DXEffect *iface, D3DXHANDLE technique, const char *name)
2365 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2366 struct d3dx_technique *tech = get_valid_technique(effect, technique);
2368 TRACE("iface %p, technique %p, name %s.\n", iface, technique, debugstr_a(name));
2370 if (tech && name)
2372 unsigned int i;
2374 for (i = 0; i < tech->pass_count; ++i)
2376 struct d3dx_pass *pass = &tech->passes[i];
2378 if (!strcmp(pass->name, name))
2380 TRACE("Returning pass %p\n", pass);
2381 return get_pass_handle(pass);
2386 WARN("Pass not found.\n");
2388 return NULL;
2391 static D3DXHANDLE WINAPI d3dx_effect_GetFunction(ID3DXEffect *iface, UINT index)
2393 FIXME("iface %p, index %u stub.\n", iface, index);
2395 return NULL;
2398 static D3DXHANDLE WINAPI d3dx_effect_GetFunctionByName(ID3DXEffect *iface, const char *name)
2400 FIXME("iface %p, name %s stub.\n", iface, debugstr_a(name));
2402 return NULL;
2405 static D3DXHANDLE WINAPI d3dx_effect_GetAnnotation(ID3DXEffect *iface, D3DXHANDLE object, UINT index)
2407 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2408 struct d3dx_parameter *annotations = NULL;
2409 unsigned int annotation_count;
2411 TRACE("iface %p, object %p, index %u.\n", iface, object, index);
2413 annotation_count = get_annotation_from_object(effect, object, &annotations);
2415 if (index < annotation_count)
2417 TRACE("Returning parameter %p\n", &annotations[index]);
2418 return get_parameter_handle(&annotations[index]);
2421 WARN("Annotation not found.\n");
2423 return NULL;
2426 static D3DXHANDLE WINAPI d3dx_effect_GetAnnotationByName(ID3DXEffect *iface, D3DXHANDLE object,
2427 const char *name)
2429 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2430 struct d3dx_parameter *annotation = NULL;
2431 struct d3dx_parameter *annotations = NULL;
2432 unsigned int annotation_count;
2434 TRACE("iface %p, object %p, name %s.\n", iface, object, debugstr_a(name));
2436 if (!name)
2438 WARN("Invalid argument specified\n");
2439 return NULL;
2442 annotation_count = get_annotation_from_object(effect, object, &annotations);
2444 annotation = get_annotation_by_name(effect, annotation_count, annotations, name);
2445 if (annotation)
2447 TRACE("Returning parameter %p\n", annotation);
2448 return get_parameter_handle(annotation);
2451 WARN("Annotation not found.\n");
2453 return NULL;
2456 static HRESULT WINAPI d3dx_effect_SetValue(ID3DXEffect *iface, D3DXHANDLE parameter,
2457 const void *data, UINT bytes)
2459 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2460 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2462 TRACE("iface %p, parameter %p, data %p, bytes %u.\n", iface, parameter, data, bytes);
2464 if (!param)
2466 WARN("Invalid parameter %p specified.\n", parameter);
2467 return D3DERR_INVALIDCALL;
2469 if (param->class == D3DXPC_OBJECT && is_param_type_sampler(param->type))
2471 WARN("Parameter is a sampler, returning E_FAIL.\n");
2472 return E_FAIL;
2475 if (data && param->bytes <= bytes)
2476 return set_value(param, data, bytes, param_get_data_and_dirtify(effect, param, param->bytes, TRUE));
2478 WARN("Invalid argument specified.\n");
2480 return D3DERR_INVALIDCALL;
2483 static HRESULT WINAPI d3dx_effect_GetValue(ID3DXEffect *iface, D3DXHANDLE parameter, void *data, UINT bytes)
2485 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2486 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2488 TRACE("iface %p, parameter %p, data %p, bytes %u.\n", iface, parameter, data, bytes);
2490 if (!param)
2492 WARN("Invalid parameter %p specified.\n", parameter);
2493 return D3DERR_INVALIDCALL;
2495 if (param->class == D3DXPC_OBJECT && is_param_type_sampler(param->type))
2497 WARN("Parameter is a sampler, returning E_FAIL.\n");
2498 return E_FAIL;
2501 if (data && param->bytes <= bytes)
2503 TRACE("Type %s.\n", debug_d3dxparameter_type(param->type));
2505 switch (param->type)
2507 case D3DXPT_VOID:
2508 case D3DXPT_BOOL:
2509 case D3DXPT_INT:
2510 case D3DXPT_FLOAT:
2511 case D3DXPT_STRING:
2512 break;
2514 case D3DXPT_VERTEXSHADER:
2515 case D3DXPT_PIXELSHADER:
2516 case D3DXPT_TEXTURE:
2517 case D3DXPT_TEXTURE1D:
2518 case D3DXPT_TEXTURE2D:
2519 case D3DXPT_TEXTURE3D:
2520 case D3DXPT_TEXTURECUBE:
2522 unsigned int i;
2524 for (i = 0; i < (param->element_count ? param->element_count : 1); ++i)
2526 IUnknown *unk = ((IUnknown **)param->data)[i];
2527 if (unk)
2528 IUnknown_AddRef(unk);
2530 break;
2533 default:
2534 FIXME("Unhandled type %s.\n", debug_d3dxparameter_type(param->type));
2535 break;
2538 TRACE("Copy %u bytes.\n", param->bytes);
2539 memcpy(data, param->data, param->bytes);
2540 return D3D_OK;
2543 WARN("Parameter not found.\n");
2545 return D3DERR_INVALIDCALL;
2548 static HRESULT WINAPI d3dx_effect_SetBool(ID3DXEffect *iface, D3DXHANDLE parameter, BOOL b)
2550 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2551 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2553 TRACE("iface %p, parameter %p, b %#x.\n", iface, parameter, b);
2555 if (param && !param->element_count && param->rows == 1 && param->columns == 1)
2557 set_number(param_get_data_and_dirtify(effect, param, sizeof(int), TRUE),
2558 param->type, &b, D3DXPT_BOOL);
2559 return D3D_OK;
2562 WARN("Parameter not found.\n");
2564 return D3DERR_INVALIDCALL;
2567 static HRESULT WINAPI d3dx_effect_GetBool(ID3DXEffect *iface, D3DXHANDLE parameter, BOOL *b)
2569 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2570 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2572 TRACE("iface %p, parameter %p, b %p.\n", iface, parameter, b);
2574 if (b && param && !param->element_count && param->rows == 1 && param->columns == 1)
2576 set_number(b, D3DXPT_BOOL, param->data, param->type);
2577 TRACE("Returning %s\n", *b ? "TRUE" : "FALSE");
2578 return D3D_OK;
2581 WARN("Parameter not found.\n");
2583 return D3DERR_INVALIDCALL;
2586 static HRESULT WINAPI d3dx_effect_SetBoolArray(ID3DXEffect *iface, D3DXHANDLE parameter, const BOOL *b, UINT count)
2588 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2589 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2590 DWORD *data;
2592 TRACE("iface %p, parameter %p, b %p, count %u.\n", iface, parameter, b, count);
2594 if (param)
2596 unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2598 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2600 switch (param->class)
2602 case D3DXPC_SCALAR:
2603 case D3DXPC_VECTOR:
2604 case D3DXPC_MATRIX_ROWS:
2605 data = param_get_data_and_dirtify(effect, param, size * sizeof(int), TRUE);
2606 for (i = 0; i < size; ++i)
2608 /* don't crop the input, use D3DXPT_INT instead of D3DXPT_BOOL */
2609 set_number(data + i, param->type, &b[i], D3DXPT_INT);
2611 return D3D_OK;
2613 case D3DXPC_OBJECT:
2614 case D3DXPC_STRUCT:
2615 break;
2617 default:
2618 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2619 break;
2623 WARN("Parameter not found.\n");
2625 return D3DERR_INVALIDCALL;
2628 static HRESULT WINAPI d3dx_effect_GetBoolArray(ID3DXEffect *iface, D3DXHANDLE parameter, BOOL *b, UINT count)
2630 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2631 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2633 TRACE("iface %p, parameter %p, b %p, count %u.\n", iface, parameter, b, count);
2635 if (b && param && (param->class == D3DXPC_SCALAR
2636 || param->class == D3DXPC_VECTOR
2637 || param->class == D3DXPC_MATRIX_ROWS
2638 || param->class == D3DXPC_MATRIX_COLUMNS))
2640 unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2642 for (i = 0; i < size; ++i)
2644 set_number(&b[i], D3DXPT_BOOL, (DWORD *)param->data + i, param->type);
2646 return D3D_OK;
2649 WARN("Parameter not found.\n");
2651 return D3DERR_INVALIDCALL;
2654 static HRESULT WINAPI d3dx_effect_SetInt(ID3DXEffect *iface, D3DXHANDLE parameter, INT n)
2656 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2657 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2659 TRACE("iface %p, parameter %p, n %d.\n", iface, parameter, n);
2661 if (param && !param->element_count)
2663 if (param->rows == 1 && param->columns == 1)
2665 DWORD value;
2667 set_number(&value, param->type, &n, D3DXPT_INT);
2668 *(DWORD *)param_get_data_and_dirtify(effect, param, sizeof(int),
2669 value != *(DWORD *)param->data) = value;
2670 return D3D_OK;
2673 /* Split the value if parameter is a vector with dimension 3 or 4. */
2674 if (param->type == D3DXPT_FLOAT
2675 && ((param->class == D3DXPC_VECTOR && param->columns != 2)
2676 || (param->class == D3DXPC_MATRIX_ROWS && param->rows != 2 && param->columns == 1)))
2678 float *data;
2680 TRACE("Vector fixup.\n");
2682 data = param_get_data_and_dirtify(effect, param,
2683 min(4, param->rows * param->columns) * sizeof(float), TRUE);
2685 data[0] = ((n & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE;
2686 data[1] = ((n & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE;
2687 data[2] = (n & 0xff) * INT_FLOAT_MULTI_INVERSE;
2688 if (param->rows * param->columns > 3)
2689 data[3] = ((n & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE;
2691 return D3D_OK;
2695 WARN("Parameter not found.\n");
2697 return D3DERR_INVALIDCALL;
2700 static HRESULT WINAPI d3dx_effect_GetInt(ID3DXEffect *iface, D3DXHANDLE parameter, INT *n)
2702 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2703 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2705 TRACE("iface %p, parameter %p, n %p.\n", iface, parameter, n);
2707 if (n && param && !param->element_count)
2709 if (param->columns == 1 && param->rows == 1)
2711 set_number(n, D3DXPT_INT, param->data, param->type);
2712 TRACE("Returning %d.\n", *n);
2713 return D3D_OK;
2716 if (param->type == D3DXPT_FLOAT &&
2717 ((param->class == D3DXPC_VECTOR && param->columns != 2)
2718 || (param->class == D3DXPC_MATRIX_ROWS && param->rows != 2 && param->columns == 1)))
2720 TRACE("Vector fixup.\n");
2722 *n = min(max(0.0f, *((float *)param->data + 2)), 1.0f) * INT_FLOAT_MULTI;
2723 *n += ((int)(min(max(0.0f, *((float *)param->data + 1)), 1.0f) * INT_FLOAT_MULTI)) << 8;
2724 *n += ((int)(min(max(0.0f, *((float *)param->data + 0)), 1.0f) * INT_FLOAT_MULTI)) << 16;
2725 if (param->columns * param->rows > 3)
2726 *n += ((int)(min(max(0.0f, *((float *)param->data + 3)), 1.0f) * INT_FLOAT_MULTI)) << 24;
2728 TRACE("Returning %d.\n", *n);
2729 return D3D_OK;
2733 WARN("Parameter not found.\n");
2735 return D3DERR_INVALIDCALL;
2738 static HRESULT WINAPI d3dx_effect_SetIntArray(ID3DXEffect *iface, D3DXHANDLE parameter, const INT *n, UINT count)
2740 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2741 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2742 DWORD *data;
2744 TRACE("iface %p, parameter %p, n %p, count %u.\n", iface, parameter, n, count);
2746 if (param)
2748 unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2750 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2752 switch (param->class)
2754 case D3DXPC_SCALAR:
2755 case D3DXPC_VECTOR:
2756 case D3DXPC_MATRIX_ROWS:
2757 data = param_get_data_and_dirtify(effect, param, size * sizeof(int), TRUE);
2758 for (i = 0; i < size; ++i)
2759 set_number(data + i, param->type, &n[i], D3DXPT_INT);
2760 return D3D_OK;
2762 case D3DXPC_OBJECT:
2763 case D3DXPC_STRUCT:
2764 break;
2766 default:
2767 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2768 break;
2772 WARN("Parameter not found.\n");
2774 return D3DERR_INVALIDCALL;
2777 static HRESULT WINAPI d3dx_effect_GetIntArray(ID3DXEffect *iface, D3DXHANDLE parameter, INT *n, UINT count)
2779 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2780 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2782 TRACE("iface %p, parameter %p, n %p, count %u.\n", iface, parameter, n, count);
2784 if (n && param && (param->class == D3DXPC_SCALAR
2785 || param->class == D3DXPC_VECTOR
2786 || param->class == D3DXPC_MATRIX_ROWS
2787 || param->class == D3DXPC_MATRIX_COLUMNS))
2789 unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2791 for (i = 0; i < size; ++i)
2792 set_number(&n[i], D3DXPT_INT, (DWORD *)param->data + i, param->type);
2793 return D3D_OK;
2796 WARN("Parameter not found.\n");
2798 return D3DERR_INVALIDCALL;
2801 static HRESULT WINAPI d3dx_effect_SetFloat(ID3DXEffect *iface, D3DXHANDLE parameter, float f)
2803 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2804 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2806 TRACE("iface %p, parameter %p, f %.8e.\n", iface, parameter, f);
2808 if (param && !param->element_count && param->rows == 1 && param->columns == 1)
2810 DWORD value;
2812 set_number(&value, param->type, &f, D3DXPT_FLOAT);
2813 *(DWORD *)param_get_data_and_dirtify(effect, param, sizeof(float),
2814 value != *(DWORD *)param->data) = value;
2815 return D3D_OK;
2818 WARN("Parameter not found.\n");
2820 return D3DERR_INVALIDCALL;
2823 static HRESULT WINAPI d3dx_effect_GetFloat(ID3DXEffect *iface, D3DXHANDLE parameter, float *f)
2825 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2826 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2828 TRACE("iface %p, parameter %p, f %p.\n", iface, parameter, f);
2830 if (f && param && !param->element_count && param->columns == 1 && param->rows == 1)
2832 set_number(f, D3DXPT_FLOAT, (DWORD *)param->data, param->type);
2833 TRACE("Returning %f.\n", *f);
2834 return D3D_OK;
2837 WARN("Parameter not found.\n");
2839 return D3DERR_INVALIDCALL;
2842 static HRESULT WINAPI d3dx_effect_SetFloatArray(ID3DXEffect *iface, D3DXHANDLE parameter,
2843 const float *f, UINT count)
2845 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2846 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2847 DWORD *data;
2849 TRACE("iface %p, parameter %p, f %p, count %u.\n", iface, parameter, f, count);
2851 if (param)
2853 unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2855 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2857 switch (param->class)
2859 case D3DXPC_SCALAR:
2860 case D3DXPC_VECTOR:
2861 case D3DXPC_MATRIX_ROWS:
2862 data = param_get_data_and_dirtify(effect, param, size * sizeof(float), TRUE);
2863 for (i = 0; i < size; ++i)
2864 set_number(data + i, param->type, &f[i], D3DXPT_FLOAT);
2865 return D3D_OK;
2867 case D3DXPC_OBJECT:
2868 case D3DXPC_STRUCT:
2869 break;
2871 default:
2872 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2873 break;
2877 WARN("Parameter not found.\n");
2879 return D3DERR_INVALIDCALL;
2882 static HRESULT WINAPI d3dx_effect_GetFloatArray(ID3DXEffect *iface, D3DXHANDLE parameter, float *f, UINT count)
2884 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2885 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2887 TRACE("iface %p, parameter %p, f %p, count %u.\n", iface, parameter, f, count);
2889 if (f && param && (param->class == D3DXPC_SCALAR
2890 || param->class == D3DXPC_VECTOR
2891 || param->class == D3DXPC_MATRIX_ROWS
2892 || param->class == D3DXPC_MATRIX_COLUMNS))
2894 unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2896 for (i = 0; i < size; ++i)
2897 set_number(&f[i], D3DXPT_FLOAT, (DWORD *)param->data + i, param->type);
2898 return D3D_OK;
2901 WARN("Parameter not found.\n");
2903 return D3DERR_INVALIDCALL;
2906 static HRESULT WINAPI d3dx_effect_SetVector(ID3DXEffect *iface, D3DXHANDLE parameter, const D3DXVECTOR4 *vector)
2908 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2909 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2911 TRACE("iface %p, parameter %p, vector %p.\n", iface, parameter, vector);
2913 if (param && !param->element_count)
2915 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2917 switch (param->class)
2919 case D3DXPC_SCALAR:
2920 case D3DXPC_VECTOR:
2921 if (param->type == D3DXPT_INT && param->bytes == 4)
2923 DWORD tmp;
2925 TRACE("INT fixup.\n");
2926 tmp = max(min(vector->z, 1.0f), 0.0f) * INT_FLOAT_MULTI;
2927 tmp += ((DWORD)(max(min(vector->y, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 8;
2928 tmp += ((DWORD)(max(min(vector->x, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 16;
2929 tmp += ((DWORD)(max(min(vector->w, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 24;
2931 *(int *)param_get_data_and_dirtify(effect, param, sizeof(int), TRUE) = tmp;
2932 return D3D_OK;
2934 if (param->type == D3DXPT_FLOAT)
2936 memcpy(param_get_data_and_dirtify(effect, param, param->columns * sizeof(float), TRUE),
2937 vector, param->columns * sizeof(float));
2938 return D3D_OK;
2941 set_vector(param, vector, param_get_data_and_dirtify(effect, param, param->columns * sizeof(float), TRUE));
2942 return D3D_OK;
2944 case D3DXPC_MATRIX_ROWS:
2945 case D3DXPC_OBJECT:
2946 case D3DXPC_STRUCT:
2947 break;
2949 default:
2950 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2951 break;
2955 WARN("Parameter not found.\n");
2957 return D3DERR_INVALIDCALL;
2960 static HRESULT WINAPI d3dx_effect_GetVector(ID3DXEffect *iface, D3DXHANDLE parameter, D3DXVECTOR4 *vector)
2962 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2963 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2965 TRACE("iface %p, parameter %p, vector %p.\n", iface, parameter, vector);
2967 if (vector && param && !param->element_count)
2969 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2971 switch (param->class)
2973 case D3DXPC_SCALAR:
2974 case D3DXPC_VECTOR:
2975 if (param->type == D3DXPT_INT && param->bytes == 4)
2977 TRACE("INT fixup.\n");
2978 vector->x = (((*(int *)param->data) & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE;
2979 vector->y = (((*(int *)param->data) & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE;
2980 vector->z = ((*(int *)param->data) & 0xff) * INT_FLOAT_MULTI_INVERSE;
2981 vector->w = (((*(int *)param->data) & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE;
2982 return D3D_OK;
2984 get_vector(param, vector);
2985 return D3D_OK;
2987 case D3DXPC_MATRIX_ROWS:
2988 case D3DXPC_OBJECT:
2989 case D3DXPC_STRUCT:
2990 break;
2992 default:
2993 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2994 break;
2998 WARN("Parameter not found.\n");
3000 return D3DERR_INVALIDCALL;
3003 static HRESULT WINAPI d3dx_effect_SetVectorArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3004 const D3DXVECTOR4 *vector, UINT count)
3006 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3007 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3009 TRACE("iface %p, parameter %p, vector %p, count %u.\n", iface, parameter, vector, count);
3011 if (param && param->element_count && param->element_count >= count)
3013 unsigned int i;
3014 BYTE *data;
3016 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3018 switch (param->class)
3020 case D3DXPC_VECTOR:
3021 data = param_get_data_and_dirtify(effect, param, count * param->columns * sizeof(float), TRUE);
3023 if (param->type == D3DXPT_FLOAT)
3025 if (param->columns == 4)
3027 memcpy(data, vector, count * 4 * sizeof(float));
3029 else
3031 for (i = 0; i < count; ++i)
3032 memcpy((float *)data + param->columns * i, vector + i,
3033 param->columns * sizeof(float));
3035 return D3D_OK;
3038 for (i = 0; i < count; ++i)
3039 set_vector(&param->members[i], &vector[i], data + i * param->columns * sizeof(float));
3041 return D3D_OK;
3043 case D3DXPC_SCALAR:
3044 case D3DXPC_MATRIX_ROWS:
3045 case D3DXPC_OBJECT:
3046 case D3DXPC_STRUCT:
3047 break;
3049 default:
3050 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3051 break;
3055 WARN("Parameter not found.\n");
3057 return D3DERR_INVALIDCALL;
3060 static HRESULT WINAPI d3dx_effect_GetVectorArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3061 D3DXVECTOR4 *vector, UINT count)
3063 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3064 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3066 TRACE("iface %p, parameter %p, vector %p, count %u.\n", iface, parameter, vector, count);
3068 if (!count)
3069 return D3D_OK;
3071 if (vector && param && count <= param->element_count)
3073 unsigned int i;
3075 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3077 switch (param->class)
3079 case D3DXPC_VECTOR:
3080 for (i = 0; i < count; ++i)
3081 get_vector(&param->members[i], &vector[i]);
3082 return D3D_OK;
3084 case D3DXPC_SCALAR:
3085 case D3DXPC_MATRIX_ROWS:
3086 case D3DXPC_OBJECT:
3087 case D3DXPC_STRUCT:
3088 break;
3090 default:
3091 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3092 break;
3096 WARN("Parameter not found.\n");
3098 return D3DERR_INVALIDCALL;
3101 static HRESULT WINAPI d3dx_effect_SetMatrix(ID3DXEffect *iface, D3DXHANDLE parameter, const D3DXMATRIX *matrix)
3103 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3104 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3106 TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3108 if (param && !param->element_count)
3110 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3112 switch (param->class)
3114 case D3DXPC_MATRIX_ROWS:
3115 set_matrix(param, matrix, param_get_data_and_dirtify(effect, param,
3116 param->rows * param->columns * sizeof(float), TRUE));
3117 return D3D_OK;
3119 case D3DXPC_SCALAR:
3120 case D3DXPC_VECTOR:
3121 case D3DXPC_OBJECT:
3122 case D3DXPC_STRUCT:
3123 break;
3125 default:
3126 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3127 break;
3131 WARN("Parameter not found.\n");
3133 return D3DERR_INVALIDCALL;
3136 static HRESULT WINAPI d3dx_effect_GetMatrix(ID3DXEffect *iface, D3DXHANDLE parameter, D3DXMATRIX *matrix)
3138 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3139 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3141 TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3143 if (matrix && param && !param->element_count)
3145 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3147 switch (param->class)
3149 case D3DXPC_MATRIX_ROWS:
3150 get_matrix(param, matrix, FALSE);
3151 return D3D_OK;
3153 case D3DXPC_SCALAR:
3154 case D3DXPC_VECTOR:
3155 case D3DXPC_OBJECT:
3156 case D3DXPC_STRUCT:
3157 break;
3159 default:
3160 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3161 break;
3165 WARN("Parameter not found.\n");
3167 return D3DERR_INVALIDCALL;
3170 static HRESULT WINAPI d3dx_effect_SetMatrixArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3171 const D3DXMATRIX *matrix, UINT count)
3173 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3174 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3176 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3178 if (param && param->element_count >= count)
3180 unsigned int i;
3181 BYTE *data;
3183 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3185 switch (param->class)
3187 case D3DXPC_MATRIX_ROWS:
3188 data = param_get_data_and_dirtify(effect, param, count * param->rows
3189 * param->columns * sizeof(float), TRUE);
3191 for (i = 0; i < count; ++i)
3192 set_matrix(&param->members[i], &matrix[i],
3193 data + i * param->rows * param->columns * sizeof(float));
3195 return D3D_OK;
3197 case D3DXPC_SCALAR:
3198 case D3DXPC_VECTOR:
3199 case D3DXPC_OBJECT:
3200 case D3DXPC_STRUCT:
3201 break;
3203 default:
3204 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3205 break;
3209 WARN("Parameter not found.\n");
3211 return D3DERR_INVALIDCALL;
3214 static HRESULT WINAPI d3dx_effect_GetMatrixArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3215 D3DXMATRIX *matrix, UINT count)
3217 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3218 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3220 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3222 if (!count)
3223 return D3D_OK;
3225 if (matrix && param && count <= param->element_count)
3227 unsigned int i;
3229 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3231 switch (param->class)
3233 case D3DXPC_MATRIX_ROWS:
3234 for (i = 0; i < count; ++i)
3235 get_matrix(&param->members[i], &matrix[i], FALSE);
3236 return D3D_OK;
3238 case D3DXPC_SCALAR:
3239 case D3DXPC_VECTOR:
3240 case D3DXPC_OBJECT:
3241 case D3DXPC_STRUCT:
3242 break;
3244 default:
3245 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3246 break;
3250 WARN("Parameter not found.\n");
3252 return D3DERR_INVALIDCALL;
3255 static HRESULT WINAPI d3dx_effect_SetMatrixPointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3256 const D3DXMATRIX **matrix, UINT count)
3258 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3259 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3261 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3263 if (param && count <= param->element_count)
3265 unsigned int i;
3266 BYTE *data;
3268 switch (param->class)
3270 case D3DXPC_MATRIX_ROWS:
3271 data = param_get_data_and_dirtify(effect, param, count * param->rows
3272 * param->columns * sizeof(float), TRUE);
3274 for (i = 0; i < count; ++i)
3275 set_matrix(&param->members[i], matrix[i], data + i * param->rows
3276 * param->columns * sizeof(float));
3278 return D3D_OK;
3280 case D3DXPC_SCALAR:
3281 case D3DXPC_VECTOR:
3282 case D3DXPC_OBJECT:
3283 break;
3285 default:
3286 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3287 break;
3291 WARN("Parameter not found.\n");
3293 return D3DERR_INVALIDCALL;
3296 static HRESULT WINAPI d3dx_effect_GetMatrixPointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3297 D3DXMATRIX **matrix, UINT count)
3299 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3300 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3302 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3304 if (!count)
3305 return D3D_OK;
3307 if (param && matrix && count <= param->element_count)
3309 unsigned int i;
3311 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3313 switch (param->class)
3315 case D3DXPC_MATRIX_ROWS:
3316 for (i = 0; i < count; ++i)
3317 get_matrix(&param->members[i], matrix[i], FALSE);
3318 return D3D_OK;
3320 case D3DXPC_SCALAR:
3321 case D3DXPC_VECTOR:
3322 case D3DXPC_OBJECT:
3323 break;
3325 default:
3326 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3327 break;
3331 WARN("Parameter not found.\n");
3333 return D3DERR_INVALIDCALL;
3336 static HRESULT WINAPI d3dx_effect_SetMatrixTranspose(ID3DXEffect *iface, D3DXHANDLE parameter,
3337 const D3DXMATRIX *matrix)
3339 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3340 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3342 TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3344 if (param && !param->element_count)
3346 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3348 switch (param->class)
3350 case D3DXPC_MATRIX_ROWS:
3351 set_matrix_transpose(param, matrix, param_get_data_and_dirtify(effect, param,
3352 param->rows * param->columns * sizeof(float), TRUE));
3353 return D3D_OK;
3355 case D3DXPC_SCALAR:
3356 case D3DXPC_VECTOR:
3357 case D3DXPC_OBJECT:
3358 case D3DXPC_STRUCT:
3359 break;
3361 default:
3362 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3363 break;
3367 WARN("Parameter not found.\n");
3369 return D3DERR_INVALIDCALL;
3372 static HRESULT WINAPI d3dx_effect_GetMatrixTranspose(ID3DXEffect *iface, D3DXHANDLE parameter,
3373 D3DXMATRIX *matrix)
3375 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3376 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3378 TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3380 if (matrix && param && !param->element_count)
3382 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3384 switch (param->class)
3386 case D3DXPC_SCALAR:
3387 case D3DXPC_VECTOR:
3388 get_matrix(param, matrix, FALSE);
3389 return D3D_OK;
3391 case D3DXPC_MATRIX_ROWS:
3392 get_matrix(param, matrix, TRUE);
3393 return D3D_OK;
3395 case D3DXPC_OBJECT:
3396 case D3DXPC_STRUCT:
3397 break;
3399 default:
3400 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3401 break;
3405 WARN("Parameter not found.\n");
3407 return D3DERR_INVALIDCALL;
3410 static HRESULT WINAPI d3dx_effect_SetMatrixTransposeArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3411 const D3DXMATRIX *matrix, UINT count)
3413 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3414 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3416 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3418 if (param && param->element_count >= count)
3420 unsigned int i;
3421 BYTE *data;
3423 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3425 switch (param->class)
3427 case D3DXPC_MATRIX_ROWS:
3428 data = param_get_data_and_dirtify(effect, param, count * param->rows
3429 * param->columns * sizeof(float), TRUE);
3431 for (i = 0; i < count; ++i)
3432 set_matrix_transpose(&param->members[i], &matrix[i], data
3433 + i * param->rows * param->columns * sizeof(float));
3435 return D3D_OK;
3437 case D3DXPC_SCALAR:
3438 case D3DXPC_VECTOR:
3439 case D3DXPC_OBJECT:
3440 case D3DXPC_STRUCT:
3441 break;
3443 default:
3444 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3445 break;
3449 WARN("Parameter not found.\n");
3451 return D3DERR_INVALIDCALL;
3454 static HRESULT WINAPI d3dx_effect_GetMatrixTransposeArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3455 D3DXMATRIX *matrix, UINT count)
3457 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3458 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3460 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3462 if (!count)
3463 return D3D_OK;
3465 if (matrix && param && count <= param->element_count)
3467 unsigned int i;
3469 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3471 switch (param->class)
3473 case D3DXPC_MATRIX_ROWS:
3474 for (i = 0; i < count; ++i)
3475 get_matrix(&param->members[i], &matrix[i], TRUE);
3476 return D3D_OK;
3478 case D3DXPC_SCALAR:
3479 case D3DXPC_VECTOR:
3480 case D3DXPC_OBJECT:
3481 case D3DXPC_STRUCT:
3482 break;
3484 default:
3485 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3486 break;
3490 WARN("Parameter not found.\n");
3492 return D3DERR_INVALIDCALL;
3495 static HRESULT WINAPI d3dx_effect_SetMatrixTransposePointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3496 const D3DXMATRIX **matrix, UINT count)
3498 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3499 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3501 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3503 if (param && count <= param->element_count)
3505 unsigned int i;
3506 BYTE *data;
3508 switch (param->class)
3510 case D3DXPC_MATRIX_ROWS:
3511 data = param_get_data_and_dirtify(effect, param, count * param->rows
3512 * param->columns * sizeof(float), TRUE);
3514 for (i = 0; i < count; ++i)
3515 set_matrix_transpose(&param->members[i], matrix[i], data
3516 + i * param->rows * param->columns * sizeof(float));
3518 return D3D_OK;
3520 case D3DXPC_SCALAR:
3521 case D3DXPC_VECTOR:
3522 case D3DXPC_OBJECT:
3523 break;
3525 default:
3526 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3527 break;
3531 WARN("Parameter not found.\n");
3533 return D3DERR_INVALIDCALL;
3536 static HRESULT WINAPI d3dx_effect_GetMatrixTransposePointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3537 D3DXMATRIX **matrix, UINT count)
3539 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3540 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3542 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3544 if (!count)
3545 return D3D_OK;
3547 if (matrix && param && count <= param->element_count)
3549 unsigned int i;
3551 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3553 switch (param->class)
3555 case D3DXPC_MATRIX_ROWS:
3556 for (i = 0; i < count; ++i)
3557 get_matrix(&param->members[i], matrix[i], TRUE);
3558 return D3D_OK;
3560 case D3DXPC_SCALAR:
3561 case D3DXPC_VECTOR:
3562 case D3DXPC_OBJECT:
3563 break;
3565 default:
3566 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3567 break;
3571 WARN("Parameter not found.\n");
3573 return D3DERR_INVALIDCALL;
3576 static HRESULT WINAPI d3dx_effect_SetString(ID3DXEffect *iface, D3DXHANDLE parameter, const char *string)
3578 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3579 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3581 TRACE("iface %p, parameter %p, string %s.\n", iface, parameter, debugstr_a(string));
3583 if (param && param->type == D3DXPT_STRING)
3584 return set_string(param_get_data_and_dirtify(effect, param, sizeof(void *), TRUE), string);
3586 WARN("Parameter not found.\n");
3588 return D3DERR_INVALIDCALL;
3591 static HRESULT WINAPI d3dx_effect_GetString(ID3DXEffect *iface, D3DXHANDLE parameter, const char **string)
3593 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3594 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3596 TRACE("iface %p, parameter %p, string %p.\n", iface, parameter, string);
3598 if (string && param && !param->element_count && param->type == D3DXPT_STRING)
3600 *string = *(const char **)param->data;
3601 TRACE("Returning %s.\n", debugstr_a(*string));
3602 return D3D_OK;
3605 WARN("Parameter not found.\n");
3607 return D3DERR_INVALIDCALL;
3610 static HRESULT WINAPI d3dx_effect_SetTexture(ID3DXEffect *iface, D3DXHANDLE parameter,
3611 IDirect3DBaseTexture9 *texture)
3613 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3614 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3616 TRACE("iface %p, parameter %p, texture %p.\n", iface, parameter, texture);
3618 if (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))
3623 IDirect3DBaseTexture9 **data = param_get_data_and_dirtify(effect, param,
3624 sizeof(void *), texture != *(IDirect3DBaseTexture9 **)param->data);
3625 IDirect3DBaseTexture9 *old_texture = *data;
3627 *data = texture;
3629 if (texture == old_texture)
3630 return D3D_OK;
3632 if (texture)
3633 IDirect3DBaseTexture9_AddRef(texture);
3634 if (old_texture)
3635 IDirect3DBaseTexture9_Release(old_texture);
3637 return D3D_OK;
3640 WARN("Parameter not found.\n");
3642 return D3DERR_INVALIDCALL;
3645 static HRESULT WINAPI d3dx_effect_GetTexture(ID3DXEffect *iface, D3DXHANDLE parameter,
3646 IDirect3DBaseTexture9 **texture)
3648 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3649 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3651 TRACE("iface %p, parameter %p, texture %p.\n", iface, parameter, texture);
3653 if (texture && param && !param->element_count
3654 && (param->type == D3DXPT_TEXTURE || param->type == D3DXPT_TEXTURE1D
3655 || param->type == D3DXPT_TEXTURE2D || param->type == D3DXPT_TEXTURE3D
3656 || param->type == D3DXPT_TEXTURECUBE))
3658 *texture = *(IDirect3DBaseTexture9 **)param->data;
3659 if (*texture)
3660 IDirect3DBaseTexture9_AddRef(*texture);
3661 TRACE("Returning %p.\n", *texture);
3662 return D3D_OK;
3665 WARN("Parameter not found.\n");
3667 return D3DERR_INVALIDCALL;
3670 static HRESULT WINAPI d3dx_effect_GetPixelShader(ID3DXEffect *iface, D3DXHANDLE parameter,
3671 IDirect3DPixelShader9 **shader)
3673 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3674 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3676 TRACE("iface %p, parameter %p, shader %p.\n", iface, parameter, shader);
3678 if (shader && param && !param->element_count && param->type == D3DXPT_PIXELSHADER)
3680 if ((*shader = *(IDirect3DPixelShader9 **)param->data))
3681 IDirect3DPixelShader9_AddRef(*shader);
3682 TRACE("Returning %p.\n", *shader);
3683 return D3D_OK;
3686 WARN("Parameter not found.\n");
3688 return D3DERR_INVALIDCALL;
3691 static HRESULT WINAPI d3dx_effect_GetVertexShader(ID3DXEffect *iface, D3DXHANDLE parameter,
3692 IDirect3DVertexShader9 **shader)
3694 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3695 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3697 TRACE("iface %p, parameter %p, shader %p.\n", iface, parameter, shader);
3699 if (shader && param && !param->element_count && param->type == D3DXPT_VERTEXSHADER)
3701 if ((*shader = *(IDirect3DVertexShader9 **)param->data))
3702 IDirect3DVertexShader9_AddRef(*shader);
3703 TRACE("Returning %p.\n", *shader);
3704 return D3D_OK;
3707 WARN("Parameter not found.\n");
3709 return D3DERR_INVALIDCALL;
3712 static HRESULT WINAPI d3dx_effect_SetArrayRange(ID3DXEffect *iface, D3DXHANDLE parameter, UINT start, UINT end)
3714 FIXME("iface %p, parameter %p, start %u, end %u stub.\n", iface, parameter, start, end);
3716 return E_NOTIMPL;
3719 /*** ID3DXEffect methods ***/
3720 static HRESULT WINAPI d3dx_effect_GetPool(ID3DXEffect *iface, ID3DXEffectPool **pool)
3722 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3724 TRACE("iface %p, pool %p.\n", effect, pool);
3726 if (!pool)
3728 WARN("Invalid argument supplied.\n");
3729 return D3DERR_INVALIDCALL;
3732 *pool = NULL;
3733 if (effect->pool)
3735 *pool = &effect->pool->ID3DXEffectPool_iface;
3736 (*pool)->lpVtbl->AddRef(*pool);
3739 TRACE("Returning pool %p.\n", *pool);
3741 return S_OK;
3744 static HRESULT WINAPI d3dx_effect_SetTechnique(ID3DXEffect *iface, D3DXHANDLE technique)
3746 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3747 struct d3dx_technique *tech = get_valid_technique(effect, technique);
3749 TRACE("iface %p, technique %p\n", iface, technique);
3751 if (tech)
3753 effect->active_technique = tech;
3754 TRACE("Technique %p\n", tech);
3755 return D3D_OK;
3758 WARN("Technique not found.\n");
3760 return D3DERR_INVALIDCALL;
3763 static D3DXHANDLE WINAPI d3dx_effect_GetCurrentTechnique(ID3DXEffect *iface)
3765 struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
3767 TRACE("iface %p\n", This);
3769 return get_technique_handle(This->active_technique);
3772 static HRESULT WINAPI d3dx_effect_ValidateTechnique(ID3DXEffect *iface, D3DXHANDLE technique)
3774 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3775 struct d3dx_technique *tech = get_valid_technique(effect, technique);
3776 HRESULT ret = D3D_OK;
3777 unsigned int i, j;
3779 FIXME("iface %p, technique %p semi-stub.\n", iface, technique);
3781 if (!tech)
3783 ret = D3DERR_INVALIDCALL;
3784 goto done;
3786 for (i = 0; i < tech->pass_count; ++i)
3788 struct d3dx_pass *pass = &tech->passes[i];
3790 for (j = 0; j < pass->state_count; ++j)
3792 struct d3dx_state *state = &pass->states[j];
3794 if (state_table[state->operation].class == SC_VERTEXSHADER
3795 || state_table[state->operation].class == SC_PIXELSHADER)
3797 struct d3dx_parameter *param;
3798 void *param_value;
3799 BOOL param_dirty;
3800 HRESULT hr;
3802 if (FAILED(hr = d3dx9_get_param_value_ptr(pass, &pass->states[j], &param_value, &param,
3803 FALSE, &param_dirty)))
3804 return hr;
3806 if (param->object_id && effect->objects[param->object_id].creation_failed)
3808 ret = E_FAIL;
3809 goto done;
3814 done:
3815 TRACE("Returning %#lx.\n", ret);
3816 return ret;
3819 static HRESULT WINAPI d3dx_effect_FindNextValidTechnique(ID3DXEffect *iface, D3DXHANDLE technique,
3820 D3DXHANDLE *next_technique)
3822 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3823 struct d3dx_technique *prev_tech, *tech;
3824 unsigned int i;
3826 TRACE("iface %p, technique %p, next_technique %p.\n", iface, technique, next_technique);
3828 if (technique)
3830 if (!(prev_tech = get_valid_technique(effect, technique)))
3831 return D3DERR_INVALIDCALL;
3833 for (i = 0; i < effect->technique_count; ++i)
3835 tech = &effect->techniques[i];
3836 if (tech == prev_tech)
3838 ++i;
3839 break;
3843 else
3845 i = 0;
3848 for (; i < effect->technique_count; ++i)
3850 tech = &effect->techniques[i];
3851 if (SUCCEEDED(d3dx_effect_ValidateTechnique(iface, get_technique_handle(tech))))
3853 *next_technique = get_technique_handle(tech);
3854 return D3D_OK;
3858 *next_technique = NULL;
3859 return S_FALSE;
3862 static BOOL walk_parameter_dep(struct d3dx_parameter *param, walk_parameter_dep_func param_func,
3863 void *data);
3865 static BOOL walk_param_eval_dep(struct d3dx_param_eval *param_eval, walk_parameter_dep_func param_func,
3866 void *data)
3868 struct d3dx_parameter **params;
3869 unsigned int i, param_count;
3871 if (!param_eval)
3872 return FALSE;
3874 params = param_eval->shader_inputs.inputs_param;
3875 param_count = param_eval->shader_inputs.input_count;
3876 for (i = 0; i < param_count; ++i)
3878 if (walk_parameter_dep(params[i], param_func, data))
3879 return TRUE;
3882 params = param_eval->pres.inputs.inputs_param;
3883 param_count = param_eval->pres.inputs.input_count;
3884 for (i = 0; i < param_count; ++i)
3886 if (walk_parameter_dep(params[i], param_func, data))
3887 return TRUE;
3889 return FALSE;
3892 static BOOL walk_state_dep(struct d3dx_state *state, walk_parameter_dep_func param_func,
3893 void *data)
3895 if (state->type == ST_CONSTANT && is_param_type_sampler(state->parameter.type))
3897 if (walk_parameter_dep(&state->parameter, param_func, data))
3898 return TRUE;
3900 else if (state->type == ST_ARRAY_SELECTOR || state->type == ST_PARAMETER)
3902 if (walk_parameter_dep(state->referenced_param, param_func, data))
3903 return TRUE;
3905 return walk_param_eval_dep(state->parameter.param_eval, param_func, data);
3908 static BOOL walk_parameter_dep(struct d3dx_parameter *param, walk_parameter_dep_func param_func,
3909 void *data)
3911 unsigned int i;
3912 unsigned int member_count;
3914 param = &param->top_level_param->param;
3915 if (param_func(data, param))
3916 return TRUE;
3918 if (walk_param_eval_dep(param->param_eval, param_func, data))
3919 return TRUE;
3921 if (param->class == D3DXPC_OBJECT && is_param_type_sampler(param->type))
3923 struct d3dx_sampler *sampler;
3924 unsigned int sampler_idx;
3925 unsigned int samplers_count = max(param->element_count, 1);
3927 for (sampler_idx = 0; sampler_idx < samplers_count; ++sampler_idx)
3929 sampler = param->element_count ? param->members[sampler_idx].data : param->data;
3930 for (i = 0; i < sampler->state_count; ++i)
3932 if (walk_state_dep(&sampler->states[i], param_func, data))
3933 return TRUE;
3936 return FALSE;
3939 member_count = param->element_count ? param->element_count : param->member_count;
3940 for (i = 0; i < member_count; ++i)
3942 if (walk_param_eval_dep(param->members[i].param_eval, param_func, data))
3943 return TRUE;
3946 return FALSE;
3949 static BOOL is_parameter_used(struct d3dx_parameter *param, struct d3dx_technique *tech)
3951 unsigned int i, j;
3952 struct d3dx_pass *pass;
3954 if (!tech || !param)
3955 return FALSE;
3957 for (i = 0; i < tech->pass_count; ++i)
3959 pass = &tech->passes[i];
3960 for (j = 0; j < pass->state_count; ++j)
3962 if (walk_state_dep(&pass->states[j], is_same_parameter, param))
3963 return TRUE;
3966 return FALSE;
3969 static BOOL WINAPI d3dx_effect_IsParameterUsed(ID3DXEffect *iface, D3DXHANDLE parameter, D3DXHANDLE technique)
3971 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3972 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3973 struct d3dx_technique *tech = get_valid_technique(effect, technique);
3974 BOOL ret;
3976 TRACE("iface %p, parameter %p, technique %p.\n", iface, parameter, technique);
3977 TRACE("param %p, name %s, tech %p.\n", param, param ? debugstr_a(param->name) : "", tech);
3979 ret = is_parameter_used(param, tech);
3980 TRACE("Returning %#x.\n", ret);
3981 return ret;
3984 static HRESULT WINAPI d3dx_effect_Begin(ID3DXEffect *iface, UINT *passes, DWORD flags)
3986 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3987 struct d3dx_technique *technique = effect->active_technique;
3989 TRACE("iface %p, passes %p, flags %#lx.\n", iface, passes, flags);
3991 if (technique)
3993 if (flags & ~(D3DXFX_DONOTSAVESTATE | D3DXFX_DONOTSAVESAMPLERSTATE | D3DXFX_DONOTSAVESHADERSTATE))
3994 WARN("Invalid flags %#lx specified.\n", flags);
3996 if (flags & D3DXFX_DONOTSAVESTATE)
3998 TRACE("State capturing disabled.\n");
4000 else
4002 HRESULT hr;
4003 unsigned int i;
4005 if (!technique->saved_state)
4007 ID3DXEffectStateManager *manager;
4009 manager = effect->manager;
4010 effect->manager = NULL;
4011 if (FAILED(hr = IDirect3DDevice9_BeginStateBlock(effect->device)))
4012 ERR("BeginStateBlock failed, hr %#lx.\n", hr);
4013 for (i = 0; i < technique->pass_count; i++)
4014 d3dx9_apply_pass_states(effect, &technique->passes[i], TRUE);
4015 if (FAILED(hr = IDirect3DDevice9_EndStateBlock(effect->device, &technique->saved_state)))
4016 ERR("EndStateBlock failed, hr %#lx.\n", hr);
4017 effect->manager = manager;
4019 if (FAILED(hr = IDirect3DStateBlock9_Capture(technique->saved_state)))
4020 ERR("StateBlock Capture failed, hr %#lx.\n", hr);
4023 if (passes)
4024 *passes = technique->pass_count;
4025 effect->started = TRUE;
4026 effect->begin_flags = flags;
4028 return D3D_OK;
4031 WARN("Invalid argument supplied.\n");
4033 return D3DERR_INVALIDCALL;
4036 static HRESULT WINAPI d3dx_effect_BeginPass(ID3DXEffect *iface, UINT pass)
4038 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4039 struct d3dx_technique *technique = effect->active_technique;
4041 TRACE("iface %p, pass %u\n", effect, pass);
4043 if (!effect->started)
4045 WARN("Effect is not started, returning D3DERR_INVALIDCALL.\n");
4046 return D3DERR_INVALIDCALL;
4049 if (technique && pass < technique->pass_count && !effect->active_pass)
4051 HRESULT hr;
4053 memset(effect->current_light, 0, sizeof(effect->current_light));
4054 memset(&effect->current_material, 0, sizeof(effect->current_material));
4056 if (SUCCEEDED(hr = d3dx9_apply_pass_states(effect, &technique->passes[pass], TRUE)))
4057 effect->active_pass = &technique->passes[pass];
4058 return hr;
4061 WARN("Invalid argument supplied.\n");
4063 return D3DERR_INVALIDCALL;
4066 static HRESULT WINAPI d3dx_effect_CommitChanges(ID3DXEffect *iface)
4068 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4070 TRACE("iface %p.\n", iface);
4072 if (!effect->active_pass)
4074 WARN("Called without an active pass.\n");
4075 return D3D_OK;
4077 return d3dx9_apply_pass_states(effect, effect->active_pass, FALSE);
4080 static HRESULT WINAPI d3dx_effect_EndPass(ID3DXEffect *iface)
4082 struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4084 TRACE("iface %p\n", This);
4086 if (This->active_pass)
4088 This->active_pass = NULL;
4089 return D3D_OK;
4092 WARN("Invalid call.\n");
4094 return D3DERR_INVALIDCALL;
4097 static HRESULT WINAPI d3dx_effect_End(ID3DXEffect *iface)
4099 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4100 struct d3dx_technique *technique = effect->active_technique;
4102 TRACE("iface %p.\n", iface);
4104 if (!effect->started)
4105 return D3D_OK;
4107 if (effect->begin_flags & D3DXFX_DONOTSAVESTATE)
4109 TRACE("State restoring disabled.\n");
4111 else
4113 HRESULT hr;
4115 if (technique && technique->saved_state)
4117 if (FAILED(hr = IDirect3DStateBlock9_Apply(technique->saved_state)))
4118 ERR("State block apply failed, hr %#lx.\n", hr);
4120 else
4121 ERR("No saved state.\n");
4124 effect->started = FALSE;
4126 return D3D_OK;
4129 static HRESULT WINAPI d3dx_effect_GetDevice(ID3DXEffect *iface, struct IDirect3DDevice9 **device)
4131 struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4133 TRACE("iface %p, device %p\n", This, device);
4135 if (!device)
4137 WARN("Invalid argument supplied.\n");
4138 return D3DERR_INVALIDCALL;
4141 IDirect3DDevice9_AddRef(This->device);
4143 *device = This->device;
4145 TRACE("Returning device %p\n", *device);
4147 return S_OK;
4150 static BOOL param_on_lost_device(void *data, struct d3dx_parameter *param)
4152 struct IDirect3DVolumeTexture9 *volume_texture;
4153 struct IDirect3DCubeTexture9 *cube_texture;
4154 struct IDirect3DTexture9 *texture;
4155 D3DSURFACE_DESC surface_desc;
4156 D3DVOLUME_DESC volume_desc;
4158 if (param->class == D3DXPC_OBJECT && !param->element_count)
4160 switch (param->type)
4162 case D3DXPT_TEXTURE:
4163 case D3DXPT_TEXTURE1D:
4164 case D3DXPT_TEXTURE2D:
4165 texture = *(IDirect3DTexture9 **)param->data;
4166 if (!texture)
4167 return FALSE;
4168 IDirect3DTexture9_GetLevelDesc(texture, 0, &surface_desc);
4169 if (surface_desc.Pool != D3DPOOL_DEFAULT)
4170 return FALSE;
4171 break;
4172 case D3DXPT_TEXTURE3D:
4173 volume_texture = *(IDirect3DVolumeTexture9 **)param->data;
4174 if (!volume_texture)
4175 return FALSE;
4176 IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
4177 if (volume_desc.Pool != D3DPOOL_DEFAULT)
4178 return FALSE;
4179 break;
4180 case D3DXPT_TEXTURECUBE:
4181 cube_texture = *(IDirect3DCubeTexture9 **)param->data;
4182 if (!cube_texture)
4183 return FALSE;
4184 IDirect3DTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
4185 if (surface_desc.Pool != D3DPOOL_DEFAULT)
4186 return FALSE;
4187 break;
4188 default:
4189 return FALSE;
4191 IUnknown_Release(*(IUnknown **)param->data);
4192 *(IUnknown **)param->data = NULL;
4194 return FALSE;
4197 static HRESULT WINAPI d3dx_effect_OnLostDevice(ID3DXEffect *iface)
4199 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4200 unsigned int i;
4202 TRACE("iface %p.\n", iface);
4204 for (i = 0; i < effect->params.count; ++i)
4205 walk_parameter_tree(&effect->params.parameters[i].param, param_on_lost_device, NULL);
4207 return D3D_OK;
4210 static HRESULT WINAPI d3dx_effect_OnResetDevice(ID3DXEffect *iface)
4212 struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4214 FIXME("(%p)->(): stub\n", This);
4216 return E_NOTIMPL;
4219 static HRESULT WINAPI d3dx_effect_SetStateManager(ID3DXEffect *iface, ID3DXEffectStateManager *manager)
4221 struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4223 TRACE("iface %p, manager %p\n", This, manager);
4225 if (manager) IUnknown_AddRef(manager);
4226 if (This->manager) IUnknown_Release(This->manager);
4228 This->manager = manager;
4230 return D3D_OK;
4233 static HRESULT WINAPI d3dx_effect_GetStateManager(ID3DXEffect *iface, ID3DXEffectStateManager **manager)
4235 struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4237 TRACE("iface %p, manager %p\n", This, manager);
4239 if (!manager)
4241 WARN("Invalid argument supplied.\n");
4242 return D3DERR_INVALIDCALL;
4245 if (This->manager) IUnknown_AddRef(This->manager);
4246 *manager = This->manager;
4248 return D3D_OK;
4251 static HRESULT WINAPI d3dx_effect_BeginParameterBlock(ID3DXEffect *iface)
4253 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4255 TRACE("iface %p.\n", iface);
4257 if (effect->current_parameter_block)
4259 WARN("Parameter block is already started.\n");
4260 return D3DERR_INVALIDCALL;
4263 effect->current_parameter_block = heap_alloc_zero(sizeof(*effect->current_parameter_block));
4264 memcpy(effect->current_parameter_block->magic_string, parameter_block_magic_string,
4265 sizeof(parameter_block_magic_string));
4266 effect->current_parameter_block->effect = effect;
4268 return D3D_OK;
4271 static D3DXHANDLE WINAPI d3dx_effect_EndParameterBlock(ID3DXEffect *iface)
4273 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4274 struct d3dx_parameter_block *ret;
4276 TRACE("iface %p.\n", iface);
4278 if (!effect->current_parameter_block)
4280 WARN("No active parameter block.\n");
4281 return NULL;
4283 ret = effect->current_parameter_block;
4285 ret->buffer = heap_realloc(ret->buffer, ret->offset);
4286 ret->size = ret->offset;
4288 effect->current_parameter_block = NULL;
4289 list_add_tail(&effect->parameter_block_list, &ret->entry);
4290 return (D3DXHANDLE)ret;
4293 static HRESULT WINAPI d3dx_effect_ApplyParameterBlock(ID3DXEffect *iface, D3DXHANDLE parameter_block)
4295 struct d3dx_parameter_block *block = get_valid_parameter_block(parameter_block);
4296 struct d3dx_recorded_parameter *record;
4298 TRACE("iface %p, parameter_block %p.\n", iface, parameter_block);
4300 if (!block || !block->offset)
4301 return D3DERR_INVALIDCALL;
4303 record = (struct d3dx_recorded_parameter *)block->buffer;
4304 while ((BYTE *)record < block->buffer + block->offset)
4306 set_value(record->param, record + 1, record->bytes,
4307 param_get_data_and_dirtify(block->effect, record->param, record->bytes, TRUE));
4308 record = (struct d3dx_recorded_parameter *)((BYTE *)record + get_recorded_parameter_size(record));
4310 assert((BYTE *)record == block->buffer + block->offset);
4311 return D3D_OK;
4314 #if D3DX_SDK_VERSION >= 26
4315 static HRESULT WINAPI d3dx_effect_DeleteParameterBlock(ID3DXEffect *iface, D3DXHANDLE parameter_block)
4317 struct d3dx_parameter_block *block = get_valid_parameter_block(parameter_block);
4318 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4319 struct d3dx_parameter_block *b;
4321 TRACE("iface %p, parameter_block %p.\n", iface, parameter_block);
4323 if (!block)
4324 return D3DERR_INVALIDCALL;
4326 LIST_FOR_EACH_ENTRY(b, &effect->parameter_block_list, struct d3dx_parameter_block, entry)
4328 if (b == block)
4330 list_remove(&b->entry);
4331 free_parameter_block(b);
4332 return D3D_OK;
4336 WARN("Block is not found in issued block list, not freeing memory.\n");
4337 return D3DERR_INVALIDCALL;
4339 #endif
4341 static bool copy_parameter(struct d3dx_effect *dst_effect, const struct d3dx_effect *src_effect,
4342 struct d3dx_parameter *dst, const struct d3dx_parameter *src)
4344 const char *src_string;
4345 char *dst_string;
4346 IUnknown *iface;
4347 size_t len;
4349 if ((src->flags & PARAMETER_FLAG_SHARED) && dst_effect->pool)
4350 return true;
4352 switch (src->type)
4354 case D3DXPT_VOID:
4355 case D3DXPT_BOOL:
4356 case D3DXPT_INT:
4357 case D3DXPT_FLOAT:
4358 memcpy(dst->data, src->data, src->bytes);
4359 break;
4361 case D3DXPT_STRING:
4362 src_string = *(char **)src->data;
4363 len = strlen(src_string);
4364 if (!(dst_string = heap_realloc(*(char **)dst->data, len + 1)))
4365 return false;
4366 *(char **)dst->data = dst_string;
4367 memcpy(dst_string, src_string, len + 1);
4368 break;
4370 case D3DXPT_TEXTURE:
4371 case D3DXPT_TEXTURE1D:
4372 case D3DXPT_TEXTURE2D:
4373 case D3DXPT_TEXTURE3D:
4374 case D3DXPT_TEXTURECUBE:
4375 case D3DXPT_PIXELSHADER:
4376 case D3DXPT_VERTEXSHADER:
4377 iface = *(IUnknown **)src->data;
4378 if (src_effect->device == dst_effect->device && iface)
4380 if (*(IUnknown **)dst->data)
4381 IUnknown_Release(*(IUnknown **)dst->data);
4382 IUnknown_AddRef(iface);
4383 *(IUnknown **)dst->data = iface;
4385 break;
4387 case D3DXPT_SAMPLER:
4388 case D3DXPT_SAMPLER1D:
4389 case D3DXPT_SAMPLER2D:
4390 case D3DXPT_SAMPLER3D:
4391 case D3DXPT_SAMPLERCUBE:
4392 /* Nothing to do; these parameters are not mutable and cannot be
4393 * retrieved using API calls. */
4394 break;
4396 default:
4397 FIXME("Unhandled parameter type %#x.\n", src->type);
4400 return true;
4403 static HRESULT WINAPI d3dx_effect_CloneEffect(ID3DXEffect *iface, IDirect3DDevice9 *device, ID3DXEffect **out)
4405 struct d3dx_effect *src = impl_from_ID3DXEffect(iface);
4406 struct d3dx_effect *dst;
4407 unsigned int i, j, k;
4408 HRESULT hr;
4410 TRACE("iface %p, device %p, out %p.\n", iface, device, out);
4412 if (!out)
4413 return D3DERR_INVALIDCALL;
4415 if (src->flags & D3DXFX_NOT_CLONEABLE)
4416 return E_FAIL;
4418 if (!device)
4419 return D3DERR_INVALIDCALL;
4421 if (!(dst = heap_alloc_zero(sizeof(*dst))))
4422 return E_OUTOFMEMORY;
4424 if (FAILED(hr = d3dx9_effect_init_from_dxbc(dst, device, src->source, src->source_size,
4425 src->flags, &src->pool->ID3DXEffectPool_iface, src->skip_constants_string)))
4427 heap_free(dst);
4428 return hr;
4431 for (i = 0; i < src->params.count; ++i)
4433 const struct d3dx_top_level_parameter *src_param = &src->params.parameters[i];
4434 struct d3dx_top_level_parameter *dst_param = &dst->params.parameters[i];
4436 copy_parameter(dst, src, &dst_param->param, &src_param->param);
4437 for (j = 0; j < src_param->annotation_count; ++j)
4438 copy_parameter(dst, src, &dst_param->annotations[j], &src_param->annotations[j]);
4441 for (i = 0; i < src->technique_count; ++i)
4443 const struct d3dx_technique *src_technique = &src->techniques[i];
4444 struct d3dx_technique *dst_technique = &dst->techniques[i];
4446 for (j = 0; j < src_technique->annotation_count; ++j)
4447 copy_parameter(dst, src, &dst_technique->annotations[j], &src_technique->annotations[j]);
4449 for (j = 0; j < src_technique->pass_count; ++j)
4451 const struct d3dx_pass *src_pass = &src_technique->passes[j];
4452 struct d3dx_pass *dst_pass = &dst_technique->passes[j];
4454 for (k = 0; k < src_pass->annotation_count; ++k)
4455 copy_parameter(dst, src, &dst_pass->annotations[k], &src_pass->annotations[k]);
4459 *out = &dst->ID3DXEffect_iface;
4460 TRACE("Created effect %p.\n", dst);
4461 return D3D_OK;
4464 #if D3DX_SDK_VERSION >= 27
4465 static HRESULT WINAPI d3dx_effect_SetRawValue(ID3DXEffect *iface, D3DXHANDLE parameter, const void *data,
4466 UINT byte_offset, UINT bytes)
4468 FIXME("iface %p, parameter %p, data %p, byte_offset %u, bytes %u stub!\n",
4469 iface, parameter, data, byte_offset, bytes);
4471 return E_NOTIMPL;
4473 #endif
4475 static const struct ID3DXEffectVtbl ID3DXEffect_Vtbl =
4477 /*** IUnknown methods ***/
4478 d3dx_effect_QueryInterface,
4479 d3dx_effect_AddRef,
4480 d3dx_effect_Release,
4481 /*** ID3DXBaseEffect methods ***/
4482 d3dx_effect_GetDesc,
4483 d3dx_effect_GetParameterDesc,
4484 d3dx_effect_GetTechniqueDesc,
4485 d3dx_effect_GetPassDesc,
4486 d3dx_effect_GetFunctionDesc,
4487 d3dx_effect_GetParameter,
4488 d3dx_effect_GetParameterByName,
4489 d3dx_effect_GetParameterBySemantic,
4490 d3dx_effect_GetParameterElement,
4491 d3dx_effect_GetTechnique,
4492 d3dx_effect_GetTechniqueByName,
4493 d3dx_effect_GetPass,
4494 d3dx_effect_GetPassByName,
4495 d3dx_effect_GetFunction,
4496 d3dx_effect_GetFunctionByName,
4497 d3dx_effect_GetAnnotation,
4498 d3dx_effect_GetAnnotationByName,
4499 d3dx_effect_SetValue,
4500 d3dx_effect_GetValue,
4501 d3dx_effect_SetBool,
4502 d3dx_effect_GetBool,
4503 d3dx_effect_SetBoolArray,
4504 d3dx_effect_GetBoolArray,
4505 d3dx_effect_SetInt,
4506 d3dx_effect_GetInt,
4507 d3dx_effect_SetIntArray,
4508 d3dx_effect_GetIntArray,
4509 d3dx_effect_SetFloat,
4510 d3dx_effect_GetFloat,
4511 d3dx_effect_SetFloatArray,
4512 d3dx_effect_GetFloatArray,
4513 d3dx_effect_SetVector,
4514 d3dx_effect_GetVector,
4515 d3dx_effect_SetVectorArray,
4516 d3dx_effect_GetVectorArray,
4517 d3dx_effect_SetMatrix,
4518 d3dx_effect_GetMatrix,
4519 d3dx_effect_SetMatrixArray,
4520 d3dx_effect_GetMatrixArray,
4521 d3dx_effect_SetMatrixPointerArray,
4522 d3dx_effect_GetMatrixPointerArray,
4523 d3dx_effect_SetMatrixTranspose,
4524 d3dx_effect_GetMatrixTranspose,
4525 d3dx_effect_SetMatrixTransposeArray,
4526 d3dx_effect_GetMatrixTransposeArray,
4527 d3dx_effect_SetMatrixTransposePointerArray,
4528 d3dx_effect_GetMatrixTransposePointerArray,
4529 d3dx_effect_SetString,
4530 d3dx_effect_GetString,
4531 d3dx_effect_SetTexture,
4532 d3dx_effect_GetTexture,
4533 d3dx_effect_GetPixelShader,
4534 d3dx_effect_GetVertexShader,
4535 d3dx_effect_SetArrayRange,
4536 /*** ID3DXEffect methods ***/
4537 d3dx_effect_GetPool,
4538 d3dx_effect_SetTechnique,
4539 d3dx_effect_GetCurrentTechnique,
4540 d3dx_effect_ValidateTechnique,
4541 d3dx_effect_FindNextValidTechnique,
4542 d3dx_effect_IsParameterUsed,
4543 d3dx_effect_Begin,
4544 d3dx_effect_BeginPass,
4545 d3dx_effect_CommitChanges,
4546 d3dx_effect_EndPass,
4547 d3dx_effect_End,
4548 d3dx_effect_GetDevice,
4549 d3dx_effect_OnLostDevice,
4550 d3dx_effect_OnResetDevice,
4551 d3dx_effect_SetStateManager,
4552 d3dx_effect_GetStateManager,
4553 d3dx_effect_BeginParameterBlock,
4554 d3dx_effect_EndParameterBlock,
4555 d3dx_effect_ApplyParameterBlock,
4556 #if D3DX_SDK_VERSION >= 26
4557 d3dx_effect_DeleteParameterBlock,
4558 #endif
4559 d3dx_effect_CloneEffect,
4560 #if D3DX_SDK_VERSION >= 27
4561 d3dx_effect_SetRawValue
4562 #endif
4565 static inline struct ID3DXEffectCompilerImpl *impl_from_ID3DXEffectCompiler(ID3DXEffectCompiler *iface)
4567 return CONTAINING_RECORD(iface, struct ID3DXEffectCompilerImpl, ID3DXEffectCompiler_iface);
4570 /*** IUnknown methods ***/
4571 static HRESULT WINAPI ID3DXEffectCompilerImpl_QueryInterface(ID3DXEffectCompiler *iface, REFIID riid, void **object)
4573 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
4575 if (IsEqualGUID(riid, &IID_IUnknown)
4576 || IsEqualGUID(riid, &IID_ID3DXEffectCompiler))
4578 iface->lpVtbl->AddRef(iface);
4579 *object = iface;
4580 return S_OK;
4583 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
4585 *object = NULL;
4586 return E_NOINTERFACE;
4589 static ULONG WINAPI ID3DXEffectCompilerImpl_AddRef(ID3DXEffectCompiler *iface)
4591 struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface);
4592 ULONG refcount = InterlockedIncrement(&compiler->ref);
4594 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
4596 return refcount;
4599 static ULONG WINAPI ID3DXEffectCompilerImpl_Release(ID3DXEffectCompiler *iface)
4601 struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface);
4602 ULONG refcount = InterlockedDecrement(&compiler->ref);
4604 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
4606 if (!refcount)
4608 heap_free(compiler);
4611 return refcount;
4614 /*** ID3DXBaseEffect methods ***/
4615 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetDesc(ID3DXEffectCompiler *iface, D3DXEFFECT_DESC *desc)
4617 FIXME("iface %p, desc %p stub!\n", iface, desc);
4619 return E_NOTIMPL;
4622 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetParameterDesc(ID3DXEffectCompiler *iface,
4623 D3DXHANDLE parameter, D3DXPARAMETER_DESC *desc)
4625 FIXME("iface %p, parameter %p, desc %p stub!\n", iface, parameter, desc);
4627 return E_NOTIMPL;
4630 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetTechniqueDesc(ID3DXEffectCompiler *iface,
4631 D3DXHANDLE technique, D3DXTECHNIQUE_DESC *desc)
4633 FIXME("iface %p, technique %p, desc %p stub!\n", iface, technique, desc);
4635 return E_NOTIMPL;
4638 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetPassDesc(ID3DXEffectCompiler *iface,
4639 D3DXHANDLE pass, D3DXPASS_DESC *desc)
4641 FIXME("iface %p, pass %p, desc %p stub!\n", iface, pass, desc);
4643 return E_NOTIMPL;
4646 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFunctionDesc(ID3DXEffectCompiler *iface,
4647 D3DXHANDLE shader, D3DXFUNCTION_DESC *desc)
4649 FIXME("iface %p, shader %p, desc %p stub!\n", iface, shader, desc);
4651 return E_NOTIMPL;
4654 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameter(ID3DXEffectCompiler *iface,
4655 D3DXHANDLE parameter, UINT index)
4657 FIXME("iface %p, parameter %p, index %u stub!\n", iface, parameter, index);
4659 return NULL;
4662 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterByName(ID3DXEffectCompiler *iface,
4663 D3DXHANDLE parameter, const char *name)
4665 FIXME("iface %p, parameter %p, name %s stub!\n", iface, parameter, debugstr_a(name));
4667 return NULL;
4670 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterBySemantic(ID3DXEffectCompiler *iface,
4671 D3DXHANDLE parameter, const char *semantic)
4673 FIXME("iface %p, parameter %p, semantic %s stub!\n", iface, parameter, debugstr_a(semantic));
4675 return NULL;
4678 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterElement(ID3DXEffectCompiler *iface,
4679 D3DXHANDLE parameter, UINT index)
4681 FIXME("iface %p, parameter %p, index %u stub!\n", iface, parameter, index);
4683 return NULL;
4686 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetTechnique(ID3DXEffectCompiler *iface, UINT index)
4688 FIXME("iface %p, index %u stub!\n", iface, index);
4690 return NULL;
4693 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetTechniqueByName(ID3DXEffectCompiler *iface, const char *name)
4695 FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
4697 return NULL;
4700 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetPass(ID3DXEffectCompiler *iface, D3DXHANDLE technique, UINT index)
4702 FIXME("iface %p, technique %p, index %u stub!\n", iface, technique, index);
4704 return NULL;
4707 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetPassByName(ID3DXEffectCompiler *iface,
4708 D3DXHANDLE technique, const char *name)
4710 FIXME("iface %p, technique %p, name %s stub!\n", iface, technique, debugstr_a(name));
4712 return NULL;
4715 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetFunction(ID3DXEffectCompiler *iface, UINT index)
4717 FIXME("iface %p, index %u stub!\n", iface, index);
4719 return NULL;
4722 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetFunctionByName(ID3DXEffectCompiler *iface, const char *name)
4724 FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
4726 return NULL;
4729 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetAnnotation(ID3DXEffectCompiler *iface,
4730 D3DXHANDLE object, UINT index)
4732 FIXME("iface %p, object %p, index %u stub!\n", iface, object, index);
4734 return NULL;
4737 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetAnnotationByName(ID3DXEffectCompiler *iface,
4738 D3DXHANDLE object, const char *name)
4740 FIXME("iface %p, object %p, name %s stub!\n", iface, object, debugstr_a(name));
4742 return NULL;
4745 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetValue(ID3DXEffectCompiler *iface,
4746 D3DXHANDLE parameter, const void *data, UINT bytes)
4748 FIXME("iface %p, parameter %p, data %p, bytes %u stub!\n", iface, parameter, data, bytes);
4750 return E_NOTIMPL;
4753 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetValue(ID3DXEffectCompiler *iface,
4754 D3DXHANDLE parameter, void *data, UINT bytes)
4756 FIXME("iface %p, parameter %p, data %p, bytes %u stub!\n", iface, parameter, data, bytes);
4758 return E_NOTIMPL;
4761 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetBool(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL b)
4763 FIXME("iface %p, parameter %p, b %#x stub!\n", iface, parameter, b);
4765 return E_NOTIMPL;
4768 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetBool(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL *b)
4770 FIXME("iface %p, parameter %p, b %p stub!\n", iface, parameter, b);
4772 return E_NOTIMPL;
4775 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetBoolArray(ID3DXEffectCompiler *iface,
4776 D3DXHANDLE parameter, const BOOL *b, UINT count)
4778 FIXME("iface %p, parameter %p, b %p, count %u stub!\n", iface, parameter, b, count);
4780 return E_NOTIMPL;
4783 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetBoolArray(ID3DXEffectCompiler *iface,
4784 D3DXHANDLE parameter, BOOL *b, UINT count)
4786 FIXME("iface %p, parameter %p, b %p, count %u stub!\n", iface, parameter, b, count);
4788 return E_NOTIMPL;
4791 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetInt(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, INT n)
4793 FIXME("iface %p, parameter %p, n %d stub!\n", iface, parameter, n);
4795 return E_NOTIMPL;
4798 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetInt(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, INT *n)
4800 FIXME("iface %p, parameter %p, n %p stub!\n", iface, parameter, n);
4802 return E_NOTIMPL;
4805 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetIntArray(ID3DXEffectCompiler *iface,
4806 D3DXHANDLE parameter, const INT *n, UINT count)
4808 FIXME("iface %p, parameter %p, n %p, count %u stub!\n", iface, parameter, n, count);
4810 return E_NOTIMPL;
4813 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetIntArray(ID3DXEffectCompiler *iface,
4814 D3DXHANDLE parameter, INT *n, UINT count)
4816 FIXME("iface %p, parameter %p, n %p, count %u stub!\n", iface, parameter, n, count);
4818 return E_NOTIMPL;
4821 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetFloat(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, float f)
4823 FIXME("iface %p, parameter %p, f %.8e stub!\n", iface, parameter, f);
4825 return E_NOTIMPL;
4828 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFloat(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, float *f)
4830 FIXME("iface %p, parameter %p, f %p stub!\n", iface, parameter, f);
4832 return E_NOTIMPL;
4835 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetFloatArray(ID3DXEffectCompiler *iface,
4836 D3DXHANDLE parameter, const float *f, UINT count)
4838 FIXME("iface %p, parameter %p, f %p, count %u stub!\n", iface, parameter, f, count);
4840 return E_NOTIMPL;
4843 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFloatArray(ID3DXEffectCompiler *iface,
4844 D3DXHANDLE parameter, float *f, UINT count)
4846 FIXME("iface %p, parameter %p, f %p, count %u stub!\n", iface, parameter, f, count);
4848 return E_NOTIMPL;
4851 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetVector(ID3DXEffectCompiler *iface,
4852 D3DXHANDLE parameter, const D3DXVECTOR4 *vector)
4854 FIXME("iface %p, parameter %p, vector %p stub!\n", iface, parameter, vector);
4856 return E_NOTIMPL;
4859 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVector(ID3DXEffectCompiler *iface,
4860 D3DXHANDLE parameter, D3DXVECTOR4 *vector)
4862 FIXME("iface %p, parameter %p, vector %p stub!\n", iface, parameter, vector);
4864 return E_NOTIMPL;
4867 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetVectorArray(ID3DXEffectCompiler *iface,
4868 D3DXHANDLE parameter, const D3DXVECTOR4 *vector, UINT count)
4870 FIXME("iface %p, parameter %p, vector %p, count %u stub!\n", iface, parameter, vector, count);
4872 return E_NOTIMPL;
4875 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVectorArray(ID3DXEffectCompiler *iface,
4876 D3DXHANDLE parameter, D3DXVECTOR4 *vector, UINT count)
4878 FIXME("iface %p, parameter %p, vector %p, count %u stub!\n", iface, parameter, vector, count);
4880 return E_NOTIMPL;
4883 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrix(ID3DXEffectCompiler *iface,
4884 D3DXHANDLE parameter, const D3DXMATRIX *matrix)
4886 FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
4888 return E_NOTIMPL;
4891 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrix(ID3DXEffectCompiler *iface,
4892 D3DXHANDLE parameter, D3DXMATRIX *matrix)
4894 FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
4896 return E_NOTIMPL;
4899 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixArray(ID3DXEffectCompiler *iface,
4900 D3DXHANDLE parameter, const D3DXMATRIX *matrix, UINT count)
4902 FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4904 return E_NOTIMPL;
4907 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixArray(ID3DXEffectCompiler *iface,
4908 D3DXHANDLE parameter, D3DXMATRIX *matrix, UINT count)
4910 FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4912 return E_NOTIMPL;
4915 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixPointerArray(ID3DXEffectCompiler *iface,
4916 D3DXHANDLE parameter, const D3DXMATRIX **matrix, UINT count)
4918 FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4920 return E_NOTIMPL;
4923 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixPointerArray(ID3DXEffectCompiler *iface,
4924 D3DXHANDLE parameter, D3DXMATRIX **matrix, UINT count)
4926 FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4928 return E_NOTIMPL;
4931 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTranspose(ID3DXEffectCompiler *iface,
4932 D3DXHANDLE parameter, const D3DXMATRIX *matrix)
4934 FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
4936 return E_NOTIMPL;
4939 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTranspose(ID3DXEffectCompiler *iface,
4940 D3DXHANDLE parameter, D3DXMATRIX *matrix)
4942 FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
4944 return E_NOTIMPL;
4947 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTransposeArray(ID3DXEffectCompiler *iface,
4948 D3DXHANDLE parameter, const D3DXMATRIX *matrix, UINT count)
4950 FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4952 return E_NOTIMPL;
4955 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTransposeArray(ID3DXEffectCompiler *iface,
4956 D3DXHANDLE parameter, D3DXMATRIX *matrix, UINT count)
4958 FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4960 return E_NOTIMPL;
4963 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTransposePointerArray(ID3DXEffectCompiler *iface,
4964 D3DXHANDLE parameter, const D3DXMATRIX **matrix, UINT count)
4966 FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4968 return E_NOTIMPL;
4971 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTransposePointerArray(ID3DXEffectCompiler *iface,
4972 D3DXHANDLE parameter, D3DXMATRIX **matrix, UINT count)
4974 FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4976 return E_NOTIMPL;
4979 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetString(ID3DXEffectCompiler *iface,
4980 D3DXHANDLE parameter, const char *string)
4982 FIXME("iface %p, parameter %p, string %s stub!\n", iface, parameter, debugstr_a(string));
4984 return E_NOTIMPL;
4987 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetString(ID3DXEffectCompiler *iface,
4988 D3DXHANDLE parameter, const char **string)
4990 FIXME("iface %p, parameter %p, string %p stub!\n", iface, parameter, string);
4992 return E_NOTIMPL;
4995 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetTexture(struct ID3DXEffectCompiler *iface,
4996 D3DXHANDLE parameter, struct IDirect3DBaseTexture9 *texture)
4998 FIXME("iface %p, parameter %p, texture %p stub!\n", iface, parameter, texture);
5000 return E_NOTIMPL;
5003 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetTexture(struct ID3DXEffectCompiler *iface,
5004 D3DXHANDLE parameter, struct IDirect3DBaseTexture9 **texture)
5006 FIXME("iface %p, parameter %p, texture %p stub!\n", iface, parameter, texture);
5008 return E_NOTIMPL;
5011 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetPixelShader(ID3DXEffectCompiler *iface,
5012 D3DXHANDLE parameter, struct IDirect3DPixelShader9 **shader)
5014 FIXME("iface %p, parameter %p, shader %p stub!\n", iface, parameter, shader);
5016 return E_NOTIMPL;
5019 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVertexShader(struct ID3DXEffectCompiler *iface,
5020 D3DXHANDLE parameter, struct IDirect3DVertexShader9 **shader)
5022 FIXME("iface %p, parameter %p, shader %p stub!\n", iface, parameter, shader);
5024 return E_NOTIMPL;
5027 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetArrayRange(ID3DXEffectCompiler *iface,
5028 D3DXHANDLE parameter, UINT start, UINT end)
5030 FIXME("iface %p, parameter %p, start %u, end %u stub!\n", iface, parameter, start, end);
5032 return E_NOTIMPL;
5035 /*** ID3DXEffectCompiler methods ***/
5036 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetLiteral(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL literal)
5038 FIXME("iface %p, parameter %p, literal %#x stub!\n", iface, parameter, literal);
5040 return E_NOTIMPL;
5043 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetLiteral(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL *literal)
5045 FIXME("iface %p, parameter %p, literal %p stub!\n", iface, parameter, literal);
5047 return E_NOTIMPL;
5050 static HRESULT WINAPI ID3DXEffectCompilerImpl_CompileEffect(ID3DXEffectCompiler *iface, DWORD flags,
5051 ID3DXBuffer **effect, ID3DXBuffer **error_msgs)
5053 FIXME("iface %p, flags %#lx, effect %p, error_msgs %p stub!\n", iface, flags, effect, error_msgs);
5055 return E_NOTIMPL;
5058 static HRESULT WINAPI ID3DXEffectCompilerImpl_CompileShader(ID3DXEffectCompiler *iface, D3DXHANDLE function,
5059 const char *target, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_msgs,
5060 ID3DXConstantTable **constant_table)
5062 FIXME("iface %p, function %p, target %s, flags %#lx, shader %p, error_msgs %p, constant_table %p stub!\n",
5063 iface, function, debugstr_a(target), flags, shader, error_msgs, constant_table);
5065 return E_NOTIMPL;
5068 static const struct ID3DXEffectCompilerVtbl ID3DXEffectCompiler_Vtbl =
5070 /*** IUnknown methods ***/
5071 ID3DXEffectCompilerImpl_QueryInterface,
5072 ID3DXEffectCompilerImpl_AddRef,
5073 ID3DXEffectCompilerImpl_Release,
5074 /*** ID3DXBaseEffect methods ***/
5075 ID3DXEffectCompilerImpl_GetDesc,
5076 ID3DXEffectCompilerImpl_GetParameterDesc,
5077 ID3DXEffectCompilerImpl_GetTechniqueDesc,
5078 ID3DXEffectCompilerImpl_GetPassDesc,
5079 ID3DXEffectCompilerImpl_GetFunctionDesc,
5080 ID3DXEffectCompilerImpl_GetParameter,
5081 ID3DXEffectCompilerImpl_GetParameterByName,
5082 ID3DXEffectCompilerImpl_GetParameterBySemantic,
5083 ID3DXEffectCompilerImpl_GetParameterElement,
5084 ID3DXEffectCompilerImpl_GetTechnique,
5085 ID3DXEffectCompilerImpl_GetTechniqueByName,
5086 ID3DXEffectCompilerImpl_GetPass,
5087 ID3DXEffectCompilerImpl_GetPassByName,
5088 ID3DXEffectCompilerImpl_GetFunction,
5089 ID3DXEffectCompilerImpl_GetFunctionByName,
5090 ID3DXEffectCompilerImpl_GetAnnotation,
5091 ID3DXEffectCompilerImpl_GetAnnotationByName,
5092 ID3DXEffectCompilerImpl_SetValue,
5093 ID3DXEffectCompilerImpl_GetValue,
5094 ID3DXEffectCompilerImpl_SetBool,
5095 ID3DXEffectCompilerImpl_GetBool,
5096 ID3DXEffectCompilerImpl_SetBoolArray,
5097 ID3DXEffectCompilerImpl_GetBoolArray,
5098 ID3DXEffectCompilerImpl_SetInt,
5099 ID3DXEffectCompilerImpl_GetInt,
5100 ID3DXEffectCompilerImpl_SetIntArray,
5101 ID3DXEffectCompilerImpl_GetIntArray,
5102 ID3DXEffectCompilerImpl_SetFloat,
5103 ID3DXEffectCompilerImpl_GetFloat,
5104 ID3DXEffectCompilerImpl_SetFloatArray,
5105 ID3DXEffectCompilerImpl_GetFloatArray,
5106 ID3DXEffectCompilerImpl_SetVector,
5107 ID3DXEffectCompilerImpl_GetVector,
5108 ID3DXEffectCompilerImpl_SetVectorArray,
5109 ID3DXEffectCompilerImpl_GetVectorArray,
5110 ID3DXEffectCompilerImpl_SetMatrix,
5111 ID3DXEffectCompilerImpl_GetMatrix,
5112 ID3DXEffectCompilerImpl_SetMatrixArray,
5113 ID3DXEffectCompilerImpl_GetMatrixArray,
5114 ID3DXEffectCompilerImpl_SetMatrixPointerArray,
5115 ID3DXEffectCompilerImpl_GetMatrixPointerArray,
5116 ID3DXEffectCompilerImpl_SetMatrixTranspose,
5117 ID3DXEffectCompilerImpl_GetMatrixTranspose,
5118 ID3DXEffectCompilerImpl_SetMatrixTransposeArray,
5119 ID3DXEffectCompilerImpl_GetMatrixTransposeArray,
5120 ID3DXEffectCompilerImpl_SetMatrixTransposePointerArray,
5121 ID3DXEffectCompilerImpl_GetMatrixTransposePointerArray,
5122 ID3DXEffectCompilerImpl_SetString,
5123 ID3DXEffectCompilerImpl_GetString,
5124 ID3DXEffectCompilerImpl_SetTexture,
5125 ID3DXEffectCompilerImpl_GetTexture,
5126 ID3DXEffectCompilerImpl_GetPixelShader,
5127 ID3DXEffectCompilerImpl_GetVertexShader,
5128 ID3DXEffectCompilerImpl_SetArrayRange,
5129 /*** ID3DXEffectCompiler methods ***/
5130 ID3DXEffectCompilerImpl_SetLiteral,
5131 ID3DXEffectCompilerImpl_GetLiteral,
5132 ID3DXEffectCompilerImpl_CompileEffect,
5133 ID3DXEffectCompilerImpl_CompileShader,
5136 static HRESULT d3dx_parse_sampler(struct d3dx_effect *effect, struct d3dx_sampler *sampler,
5137 const char *data, const char **ptr, struct d3dx_object *objects)
5139 HRESULT hr;
5140 UINT i;
5142 sampler->state_count = read_u32(ptr);
5143 TRACE("Count: %u\n", sampler->state_count);
5145 sampler->states = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*sampler->states) * sampler->state_count);
5146 if (!sampler->states)
5148 ERR("Out of memory\n");
5149 return E_OUTOFMEMORY;
5152 for (i = 0; i < sampler->state_count; ++i)
5154 hr = d3dx_parse_state(effect, &sampler->states[i], data, ptr, objects);
5155 if (hr != D3D_OK)
5157 WARN("Failed to parse state %u\n", i);
5158 goto err_out;
5162 return D3D_OK;
5164 err_out:
5166 for (i = 0; i < sampler->state_count; ++i)
5168 free_state(&sampler->states[i]);
5170 HeapFree(GetProcessHeap(), 0, sampler->states);
5171 sampler->states = NULL;
5173 return hr;
5176 static HRESULT d3dx_parse_value(struct d3dx_effect *effect, struct d3dx_parameter *param,
5177 void *value, const char *data, const char **ptr, struct d3dx_object *objects)
5179 unsigned int i;
5180 HRESULT hr;
5181 UINT old_size = 0;
5183 if (param->element_count)
5185 param->data = value;
5187 for (i = 0; i < param->element_count; ++i)
5189 struct d3dx_parameter *member = &param->members[i];
5191 hr = d3dx_parse_value(effect, member, value ? (char *)value + old_size : NULL, data, ptr, objects);
5192 if (hr != D3D_OK)
5194 WARN("Failed to parse value %u\n", i);
5195 return hr;
5198 old_size += member->bytes;
5201 return D3D_OK;
5204 switch(param->class)
5206 case D3DXPC_SCALAR:
5207 case D3DXPC_VECTOR:
5208 case D3DXPC_MATRIX_ROWS:
5209 case D3DXPC_MATRIX_COLUMNS:
5210 param->data = value;
5211 break;
5213 case D3DXPC_STRUCT:
5214 param->data = value;
5216 for (i = 0; i < param->member_count; ++i)
5218 struct d3dx_parameter *member = &param->members[i];
5220 hr = d3dx_parse_value(effect, member, (char *)value + old_size, data, ptr, objects);
5221 if (hr != D3D_OK)
5223 WARN("Failed to parse value %u\n", i);
5224 return hr;
5227 old_size += member->bytes;
5229 break;
5231 case D3DXPC_OBJECT:
5232 switch (param->type)
5234 case D3DXPT_STRING:
5235 case D3DXPT_TEXTURE:
5236 case D3DXPT_TEXTURE1D:
5237 case D3DXPT_TEXTURE2D:
5238 case D3DXPT_TEXTURE3D:
5239 case D3DXPT_TEXTURECUBE:
5240 case D3DXPT_PIXELSHADER:
5241 case D3DXPT_VERTEXSHADER:
5242 param->object_id = read_u32(ptr);
5243 TRACE("Id: %u\n", param->object_id);
5244 objects[param->object_id].param = param;
5245 param->data = value;
5246 break;
5248 case D3DXPT_SAMPLER:
5249 case D3DXPT_SAMPLER1D:
5250 case D3DXPT_SAMPLER2D:
5251 case D3DXPT_SAMPLER3D:
5252 case D3DXPT_SAMPLERCUBE:
5254 struct d3dx_sampler *sampler;
5256 sampler = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*sampler));
5257 if (!sampler)
5258 return E_OUTOFMEMORY;
5260 hr = d3dx_parse_sampler(effect, sampler, data, ptr, objects);
5261 if (hr != D3D_OK)
5263 HeapFree(GetProcessHeap(), 0, sampler);
5264 WARN("Failed to parse sampler\n");
5265 return hr;
5268 param->data = sampler;
5269 break;
5272 default:
5273 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(param->type));
5274 break;
5276 break;
5278 default:
5279 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
5280 break;
5283 return D3D_OK;
5286 static HRESULT d3dx_parse_init_value(struct d3dx_effect *effect, struct d3dx_parameter *param,
5287 const char *data, const char *ptr, struct d3dx_object *objects)
5289 UINT size = param->bytes;
5290 HRESULT hr;
5291 void *value = NULL;
5293 TRACE("param size: %u\n", size);
5295 if (size)
5297 value = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
5298 if (!value)
5300 ERR("Failed to allocate data memory.\n");
5301 return E_OUTOFMEMORY;
5304 switch(param->class)
5306 case D3DXPC_OBJECT:
5307 break;
5309 case D3DXPC_SCALAR:
5310 case D3DXPC_VECTOR:
5311 case D3DXPC_MATRIX_ROWS:
5312 case D3DXPC_MATRIX_COLUMNS:
5313 case D3DXPC_STRUCT:
5314 TRACE("Data: %s.\n", debugstr_an(ptr, size));
5315 memcpy(value, ptr, size);
5316 break;
5318 default:
5319 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
5320 break;
5324 hr = d3dx_parse_value(effect, param, value, data, &ptr, objects);
5325 if (hr != D3D_OK)
5327 WARN("Failed to parse value\n");
5328 HeapFree(GetProcessHeap(), 0, value);
5329 return hr;
5332 return D3D_OK;
5335 static HRESULT d3dx9_parse_name(char **name, const char *ptr)
5337 unsigned int size;
5339 size = read_u32(&ptr);
5340 TRACE("Name size: %#x.\n", size);
5342 if (!size)
5344 return D3D_OK;
5347 *name = HeapAlloc(GetProcessHeap(), 0, size);
5348 if (!*name)
5350 ERR("Failed to allocate name memory.\n");
5351 return E_OUTOFMEMORY;
5354 TRACE("Name: %s.\n", debugstr_an(ptr, size));
5355 memcpy(*name, ptr, size);
5357 return D3D_OK;
5360 static HRESULT d3dx9_copy_data(struct d3dx_effect *effect, unsigned int object_id, const char **ptr)
5362 struct d3dx_object *object = &effect->objects[object_id];
5364 if (object->size || object->data)
5366 if (object_id)
5367 FIXME("Overwriting object id %u!\n", object_id);
5368 else
5369 TRACE("Overwriting object id 0.\n");
5371 HeapFree(GetProcessHeap(), 0, object->data);
5372 object->data = NULL;
5375 object->size = read_u32(ptr);
5376 TRACE("Data size: %#x.\n", object->size);
5378 if (!object->size)
5379 return D3D_OK;
5381 object->data = HeapAlloc(GetProcessHeap(), 0, object->size);
5382 if (!object->data)
5384 ERR("Failed to allocate object memory.\n");
5385 return E_OUTOFMEMORY;
5388 TRACE("Data: %s.\n", debugstr_an(*ptr, object->size));
5389 memcpy(object->data, *ptr, object->size);
5391 *ptr += ((object->size + 3) & ~3);
5393 return D3D_OK;
5396 static void param_set_magic_number(struct d3dx_parameter *param)
5398 memcpy(param->magic_string, parameter_magic_string, sizeof(parameter_magic_string));
5401 static void add_param_to_tree(struct d3dx_effect *effect, struct d3dx_parameter *param,
5402 struct d3dx_parameter *parent, char separator, unsigned int element)
5404 const char *parent_name = parent ? parent->full_name : NULL;
5405 unsigned int i;
5407 TRACE("Adding parameter %p (%s - parent %p, element %u) to the rbtree.\n",
5408 param, debugstr_a(param->name), parent, element);
5410 if (parent_name)
5412 unsigned int parent_name_len = strlen(parent_name);
5413 unsigned int name_len = strlen(param->name);
5414 unsigned int part_str_len;
5415 unsigned int len;
5416 char part_str[16];
5418 if (separator == '[')
5420 sprintf(part_str, "[%u]", element);
5421 part_str_len = strlen(part_str);
5422 name_len = 0;
5424 else
5426 part_str[0] = separator;
5427 part_str[1] = 0;
5428 part_str_len = 1;
5430 len = parent_name_len + part_str_len + name_len + 1;
5432 if (!(param->full_name = heap_alloc(len)))
5434 ERR("Out of memory.\n");
5435 return;
5438 memcpy(param->full_name, parent_name, parent_name_len);
5439 memcpy(param->full_name + parent_name_len, part_str, part_str_len);
5440 memcpy(param->full_name + parent_name_len + part_str_len, param->name, name_len);
5441 param->full_name[len - 1] = 0;
5443 else
5445 unsigned int len = strlen(param->name) + 1;
5447 if (!(param->full_name = heap_alloc(len)))
5449 ERR("Out of memory.\n");
5450 return;
5453 memcpy(param->full_name, param->name, len);
5455 TRACE("Full name is %s.\n", param->full_name);
5456 wine_rb_put(&effect->params.tree, param->full_name, &param->rb_entry);
5458 if (is_top_level_parameter(param))
5459 for (i = 0; i < param->top_level_param->annotation_count; ++i)
5460 add_param_to_tree(effect, &param->top_level_param->annotations[i], param, '@', 0);
5462 if (param->element_count)
5463 for (i = 0; i < param->element_count; ++i)
5464 add_param_to_tree(effect, &param->members[i], param, '[', i);
5465 else
5466 for (i = 0; i < param->member_count; ++i)
5467 add_param_to_tree(effect, &param->members[i], param, '.', 0);
5470 static HRESULT d3dx_parse_effect_typedef(struct d3dx_effect *effect, struct d3dx_parameter *param,
5471 const char *data, const char **ptr, struct d3dx_parameter *parent, UINT flags)
5473 uint32_t offset;
5474 HRESULT hr;
5475 UINT i;
5477 param->flags = flags;
5479 if (!parent)
5481 param->type = read_u32(ptr);
5482 TRACE("Type: %s.\n", debug_d3dxparameter_type(param->type));
5484 param->class = read_u32(ptr);
5485 TRACE("Class: %s.\n", debug_d3dxparameter_class(param->class));
5487 offset = read_u32(ptr);
5488 TRACE("Type name offset: %#x.\n", offset);
5489 hr = d3dx9_parse_name(&param->name, data + offset);
5490 if (hr != D3D_OK)
5492 WARN("Failed to parse name\n");
5493 goto err_out;
5496 offset = read_u32(ptr);
5497 TRACE("Type semantic offset: %#x.\n", offset);
5498 hr = d3dx9_parse_name(&param->semantic, data + offset);
5499 if (hr != D3D_OK)
5501 WARN("Failed to parse semantic\n");
5502 goto err_out;
5505 param->element_count = read_u32(ptr);
5506 TRACE("Elements: %u.\n", param->element_count);
5508 switch (param->class)
5510 case D3DXPC_VECTOR:
5511 param->columns = read_u32(ptr);
5512 TRACE("Columns: %u.\n", param->columns);
5514 param->rows = read_u32(ptr);
5515 TRACE("Rows: %u.\n", param->rows);
5517 /* sizeof(DWORD) * rows * columns */
5518 param->bytes = 4 * param->rows * param->columns;
5519 break;
5521 case D3DXPC_SCALAR:
5522 case D3DXPC_MATRIX_ROWS:
5523 case D3DXPC_MATRIX_COLUMNS:
5524 param->rows = read_u32(ptr);
5525 TRACE("Rows: %u.\n", param->rows);
5527 param->columns = read_u32(ptr);
5528 TRACE("Columns: %u.\n", param->columns);
5530 /* sizeof(DWORD) * rows * columns */
5531 param->bytes = 4 * param->rows * param->columns;
5532 break;
5534 case D3DXPC_STRUCT:
5535 param->member_count = read_u32(ptr);
5536 TRACE("Members: %u.\n", param->member_count);
5537 break;
5539 case D3DXPC_OBJECT:
5540 switch (param->type)
5542 case D3DXPT_STRING:
5543 case D3DXPT_PIXELSHADER:
5544 case D3DXPT_VERTEXSHADER:
5545 case D3DXPT_TEXTURE:
5546 case D3DXPT_TEXTURE1D:
5547 case D3DXPT_TEXTURE2D:
5548 case D3DXPT_TEXTURE3D:
5549 case D3DXPT_TEXTURECUBE:
5550 param->bytes = sizeof(void *);
5551 break;
5553 case D3DXPT_SAMPLER:
5554 case D3DXPT_SAMPLER1D:
5555 case D3DXPT_SAMPLER2D:
5556 case D3DXPT_SAMPLER3D:
5557 case D3DXPT_SAMPLERCUBE:
5558 param->bytes = 0;
5559 break;
5561 default:
5562 FIXME("Unhandled type %s.\n", debug_d3dxparameter_type(param->type));
5563 break;
5565 break;
5567 default:
5568 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
5569 break;
5572 else
5574 /* elements */
5575 param->type = parent->type;
5576 param->class = parent->class;
5577 param->name = parent->name;
5578 param->semantic = parent->semantic;
5579 param->element_count = 0;
5580 param->member_count = parent->member_count;
5581 param->bytes = parent->bytes;
5582 param->rows = parent->rows;
5583 param->columns = parent->columns;
5586 if (param->element_count)
5588 unsigned int param_bytes = 0;
5589 const char *save_ptr = *ptr;
5591 param->members = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*param->members) * param->element_count);
5592 if (!param->members)
5594 ERR("Out of memory\n");
5595 hr = E_OUTOFMEMORY;
5596 goto err_out;
5599 for (i = 0; i < param->element_count; ++i)
5601 *ptr = save_ptr;
5603 param_set_magic_number(&param->members[i]);
5604 hr = d3dx_parse_effect_typedef(effect, &param->members[i], data, ptr, param, flags);
5605 if (hr != D3D_OK)
5607 WARN("Failed to parse member %u\n", i);
5608 goto err_out;
5611 param_bytes += param->members[i].bytes;
5614 param->bytes = param_bytes;
5616 else if (param->member_count)
5618 param->members = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*param->members) * param->member_count);
5619 if (!param->members)
5621 ERR("Out of memory\n");
5622 hr = E_OUTOFMEMORY;
5623 goto err_out;
5626 for (i = 0; i < param->member_count; ++i)
5628 param_set_magic_number(&param->members[i]);
5629 hr = d3dx_parse_effect_typedef(effect, &param->members[i], data, ptr, NULL, flags);
5630 if (hr != D3D_OK)
5632 WARN("Failed to parse member %u\n", i);
5633 goto err_out;
5636 param->bytes += param->members[i].bytes;
5639 return D3D_OK;
5641 err_out:
5643 if (param->members)
5645 unsigned int count = param->element_count ? param->element_count : param->member_count;
5647 for (i = 0; i < count; ++i)
5648 free_parameter(&param->members[i], param->element_count != 0, TRUE);
5649 HeapFree(GetProcessHeap(), 0, param->members);
5650 param->members = NULL;
5653 if (!parent)
5655 HeapFree(GetProcessHeap(), 0, param->name);
5656 HeapFree(GetProcessHeap(), 0, param->semantic);
5658 param->name = NULL;
5659 param->semantic = NULL;
5661 return hr;
5664 static HRESULT d3dx_parse_effect_annotation(struct d3dx_effect *effect, struct d3dx_parameter *anno,
5665 const char *data, const char **ptr, struct d3dx_object *objects)
5667 const char *ptr2;
5668 uint32_t offset;
5669 HRESULT hr;
5671 anno->flags = D3DX_PARAMETER_ANNOTATION;
5673 offset = read_u32(ptr);
5674 TRACE("Typedef offset: %#x.\n", offset);
5675 ptr2 = data + offset;
5676 hr = d3dx_parse_effect_typedef(effect, anno, data, &ptr2, NULL, D3DX_PARAMETER_ANNOTATION);
5677 if (hr != D3D_OK)
5679 WARN("Failed to parse type definition.\n");
5680 return hr;
5683 offset = read_u32(ptr);
5684 TRACE("Value offset: %#x.\n", offset);
5685 hr = d3dx_parse_init_value(effect, anno, data, data + offset, objects);
5686 if (hr != D3D_OK)
5688 WARN("Failed to parse value.\n");
5689 return hr;
5692 return D3D_OK;
5695 static HRESULT d3dx_parse_state(struct d3dx_effect *effect, struct d3dx_state *state,
5696 const char *data, const char **ptr, struct d3dx_object *objects)
5698 struct d3dx_parameter *param = &state->parameter;
5699 enum STATE_CLASS state_class;
5700 const char *ptr2;
5701 uint32_t offset;
5702 void *new_data;
5703 HRESULT hr;
5705 state->type = ST_CONSTANT;
5707 state->operation = read_u32(ptr);
5708 if (state->operation >= ARRAY_SIZE(state_table))
5710 WARN("Unknown state operation %u.\n", state->operation);
5711 return D3DERR_INVALIDCALL;
5713 TRACE("Operation: %#x (%s).\n", state->operation, state_table[state->operation].name);
5715 state->index = read_u32(ptr);
5716 TRACE("Index: %#x.\n", state->index);
5718 offset = read_u32(ptr);
5719 TRACE("Typedef offset: %#x.\n", offset);
5720 ptr2 = data + offset;
5721 hr = d3dx_parse_effect_typedef(effect, param, data, &ptr2, NULL, 0);
5722 if (hr != D3D_OK)
5724 WARN("Failed to parse type definition\n");
5725 goto err_out;
5728 offset = read_u32(ptr);
5729 TRACE("Value offset: %#x.\n", offset);
5730 hr = d3dx_parse_init_value(effect, param, data, data + offset, objects);
5731 if (hr != D3D_OK)
5733 WARN("Failed to parse value\n");
5734 goto err_out;
5737 if (((state_class = state_table[state->operation].class) == SC_VERTEXSHADER
5738 || state_class == SC_PIXELSHADER || state_class == SC_TEXTURE)
5739 && param->bytes < sizeof(void *))
5741 if (param->type != D3DXPT_INT || *(unsigned int *)param->data)
5743 FIXME("Unexpected parameter for object, param->type %#x, param->class %#x, *param->data %#x.\n",
5744 param->type, param->class, *(unsigned int *)param->data);
5745 hr = D3DXERR_INVALIDDATA;
5746 goto err_out;
5749 new_data = heap_realloc(param->data, sizeof(void *));
5750 if (!new_data)
5752 ERR("Out of memory.\n");
5753 hr = E_OUTOFMEMORY;
5754 goto err_out;
5756 memset(new_data, 0, sizeof(void *));
5757 param->data = new_data;
5758 param->bytes = sizeof(void *);
5761 return D3D_OK;
5763 err_out:
5765 free_parameter(param, FALSE, FALSE);
5767 return hr;
5770 static HRESULT d3dx_parse_effect_parameter(struct d3dx_effect *effect, struct d3dx_top_level_parameter *param,
5771 const char *data, const char **ptr, struct d3dx_object *objects)
5773 const char *ptr2;
5774 uint32_t offset;
5775 unsigned int i;
5776 HRESULT hr;
5778 offset = read_u32(ptr);
5779 TRACE("Typedef offset: %#x.\n", offset);
5780 ptr2 = data + offset;
5782 offset = read_u32(ptr);
5783 TRACE("Value offset: %#x.\n", offset);
5785 param->param.flags = read_u32(ptr);
5786 TRACE("Flags: %#x.\n", param->param.flags);
5788 param->annotation_count = read_u32(ptr);
5789 TRACE("Annotation count: %u.\n", param->annotation_count);
5791 hr = d3dx_parse_effect_typedef(effect, &param->param, data, &ptr2, NULL, param->param.flags);
5792 if (hr != D3D_OK)
5794 WARN("Failed to parse type definition.\n");
5795 return hr;
5798 hr = d3dx_parse_init_value(effect, &param->param, data, data + offset, objects);
5799 if (hr != D3D_OK)
5801 WARN("Failed to parse value.\n");
5802 return hr;
5805 if (param->annotation_count)
5807 param->annotations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5808 sizeof(*param->annotations) * param->annotation_count);
5809 if (!param->annotations)
5811 ERR("Out of memory.\n");
5812 hr = E_OUTOFMEMORY;
5813 goto err_out;
5816 for (i = 0; i < param->annotation_count; ++i)
5818 param_set_magic_number(&param->annotations[i]);
5819 hr = d3dx_parse_effect_annotation(effect, &param->annotations[i], data, ptr, objects);
5820 if (hr != D3D_OK)
5822 WARN("Failed to parse annotation.\n");
5823 goto err_out;
5828 return D3D_OK;
5830 err_out:
5832 if (param->annotations)
5834 for (i = 0; i < param->annotation_count; ++i)
5835 free_parameter(&param->annotations[i], FALSE, FALSE);
5836 HeapFree(GetProcessHeap(), 0, param->annotations);
5837 param->annotations = NULL;
5840 return hr;
5843 static HRESULT d3dx_parse_effect_pass(struct d3dx_effect *effect, struct d3dx_pass *pass,
5844 const char *data, const char **ptr, struct d3dx_object *objects)
5846 struct d3dx_state *states = NULL;
5847 char *name = NULL;
5848 uint32_t offset;
5849 unsigned int i;
5850 HRESULT hr;
5852 offset = read_u32(ptr);
5853 TRACE("Pass name offset: %#x.\n", offset);
5854 hr = d3dx9_parse_name(&name, data + offset);
5855 if (hr != D3D_OK)
5857 WARN("Failed to parse name.\n");
5858 goto err_out;
5861 pass->annotation_count = read_u32(ptr);
5862 TRACE("Annotation count: %u.\n", pass->annotation_count);
5864 pass->state_count = read_u32(ptr);
5865 TRACE("State count: %u.\n", pass->state_count);
5867 if (pass->annotation_count)
5869 pass->annotations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5870 sizeof(*pass->annotations) * pass->annotation_count);
5871 if (!pass->annotations)
5873 ERR("Out of memory\n");
5874 hr = E_OUTOFMEMORY;
5875 goto err_out;
5878 for (i = 0; i < pass->annotation_count; ++i)
5880 param_set_magic_number(&pass->annotations[i]);
5881 hr = d3dx_parse_effect_annotation(effect, &pass->annotations[i], data, ptr, objects);
5882 if (hr != D3D_OK)
5884 WARN("Failed to parse annotation %u\n", i);
5885 goto err_out;
5890 if (pass->state_count)
5892 states = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*states) * pass->state_count);
5893 if (!states)
5895 ERR("Out of memory\n");
5896 hr = E_OUTOFMEMORY;
5897 goto err_out;
5900 for (i = 0; i < pass->state_count; ++i)
5902 hr = d3dx_parse_state(effect, &states[i], data, ptr, objects);
5903 if (hr != D3D_OK)
5905 WARN("Failed to parse annotation %u\n", i);
5906 goto err_out;
5911 pass->name = name;
5912 pass->states = states;
5914 return D3D_OK;
5916 err_out:
5918 if (pass->annotations)
5920 for (i = 0; i < pass->annotation_count; ++i)
5921 free_parameter(&pass->annotations[i], FALSE, FALSE);
5922 HeapFree(GetProcessHeap(), 0, pass->annotations);
5923 pass->annotations = NULL;
5926 if (states)
5928 for (i = 0; i < pass->state_count; ++i)
5930 free_state(&states[i]);
5932 HeapFree(GetProcessHeap(), 0, states);
5935 HeapFree(GetProcessHeap(), 0, name);
5937 return hr;
5940 static HRESULT d3dx_parse_effect_technique(struct d3dx_effect *effect, struct d3dx_technique *technique,
5941 const char *data, const char **ptr, struct d3dx_object *objects)
5943 char *name = NULL;
5944 uint32_t offset;
5945 unsigned int i;
5946 HRESULT hr;
5948 offset = read_u32(ptr);
5949 TRACE("Technique name offset: %#x.\n", offset);
5950 hr = d3dx9_parse_name(&name, data + offset);
5951 if (hr != D3D_OK)
5953 WARN("Failed to parse name\n");
5954 goto err_out;
5957 technique->annotation_count = read_u32(ptr);
5958 TRACE("Annotation count: %u.\n", technique->annotation_count);
5960 technique->pass_count = read_u32(ptr);
5961 TRACE("Pass count: %u.\n", technique->pass_count);
5963 if (technique->annotation_count)
5965 technique->annotations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5966 sizeof(*technique->annotations) * technique->annotation_count);
5967 if (!technique->annotations)
5969 ERR("Out of memory\n");
5970 hr = E_OUTOFMEMORY;
5971 goto err_out;
5974 for (i = 0; i < technique->annotation_count; ++i)
5976 param_set_magic_number(&technique->annotations[i]);
5977 hr = d3dx_parse_effect_annotation(effect, &technique->annotations[i], data, ptr, objects);
5978 if (hr != D3D_OK)
5980 WARN("Failed to parse annotation %u\n", i);
5981 goto err_out;
5986 if (technique->pass_count)
5988 technique->passes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5989 sizeof(*technique->passes) * technique->pass_count);
5990 if (!technique->passes)
5992 ERR("Out of memory\n");
5993 hr = E_OUTOFMEMORY;
5994 goto err_out;
5997 for (i = 0; i < technique->pass_count; ++i)
5999 hr = d3dx_parse_effect_pass(effect, &technique->passes[i], data, ptr, objects);
6000 if (hr != D3D_OK)
6002 WARN("Failed to parse pass %u\n", i);
6003 goto err_out;
6008 technique->name = name;
6010 return D3D_OK;
6012 err_out:
6014 if (technique->passes)
6016 for (i = 0; i < technique->pass_count; ++i)
6017 free_pass(&technique->passes[i]);
6018 HeapFree(GetProcessHeap(), 0, technique->passes);
6019 technique->passes = NULL;
6022 if (technique->annotations)
6024 for (i = 0; i < technique->annotation_count; ++i)
6025 free_parameter(&technique->annotations[i], FALSE, FALSE);
6026 HeapFree(GetProcessHeap(), 0, technique->annotations);
6027 technique->annotations = NULL;
6030 HeapFree(GetProcessHeap(), 0, name);
6032 return hr;
6035 static HRESULT d3dx9_create_object(struct d3dx_effect *effect, struct d3dx_object *object)
6037 struct d3dx_parameter *param = object->param;
6038 IDirect3DDevice9 *device = effect->device;
6039 HRESULT hr;
6041 if (*(char **)param->data)
6042 ERR("Parameter data already allocated.\n");
6044 switch (param->type)
6046 case D3DXPT_STRING:
6047 *(char **)param->data = HeapAlloc(GetProcessHeap(), 0, object->size);
6048 if (!*(char **)param->data)
6050 ERR("Out of memory.\n");
6051 return E_OUTOFMEMORY;
6053 memcpy(*(char **)param->data, object->data, object->size);
6054 break;
6055 case D3DXPT_VERTEXSHADER:
6056 if (FAILED(hr = IDirect3DDevice9_CreateVertexShader(device, object->data,
6057 (IDirect3DVertexShader9 **)param->data)))
6059 WARN("Failed to create vertex shader.\n");
6060 object->creation_failed = TRUE;
6062 break;
6063 case D3DXPT_PIXELSHADER:
6064 if (FAILED(hr = IDirect3DDevice9_CreatePixelShader(device, object->data,
6065 (IDirect3DPixelShader9 **)param->data)))
6067 WARN("Failed to create pixel shader.\n");
6068 object->creation_failed = TRUE;
6070 break;
6071 default:
6072 break;
6074 return D3D_OK;
6077 static HRESULT d3dx_parse_array_selector(struct d3dx_effect *effect, struct d3dx_state *state,
6078 const char **skip_constants, unsigned int skip_constants_count)
6080 struct d3dx_parameter *param = &state->parameter;
6081 struct d3dx_object *object = &effect->objects[param->object_id];
6082 char *ptr = object->data;
6083 uint32_t string_size;
6084 HRESULT ret;
6086 TRACE("Parsing array entry selection state for parameter %p.\n", param);
6088 string_size = *(uint32_t *)ptr;
6089 state->referenced_param = get_parameter_by_name(&effect->params, NULL, ptr + 4);
6090 if (state->referenced_param)
6092 TRACE("Mapping to parameter %s.\n", debugstr_a(state->referenced_param->name));
6094 else
6096 FIXME("Referenced parameter %s not found.\n", ptr + 4);
6097 return D3DXERR_INVALIDDATA;
6099 TRACE("Unknown u32: 0x%.8x.\n", *(uint32_t *)(ptr + string_size));
6101 if (string_size % sizeof(uint32_t))
6102 FIXME("Unaligned string_size %u.\n", string_size);
6103 if (FAILED(ret = d3dx_create_param_eval(&effect->params, (uint32_t *)(ptr + string_size) + 1,
6104 object->size - (string_size + sizeof(uint32_t)), D3DXPT_INT, &param->param_eval,
6105 get_version_counter_ptr(effect), NULL, 0)))
6106 return ret;
6107 ret = D3D_OK;
6108 param = state->referenced_param;
6109 if (param->type == D3DXPT_VERTEXSHADER || param->type == D3DXPT_PIXELSHADER)
6111 unsigned int i;
6113 for (i = 0; i < param->element_count; i++)
6115 if (param->members[i].type != param->type)
6117 FIXME("Unexpected member parameter type %u, expected %u.\n", param->members[i].type, param->type);
6118 return D3DXERR_INVALIDDATA;
6120 if (!param->members[i].param_eval)
6122 TRACE("Creating preshader for object %u.\n", param->members[i].object_id);
6123 object = &effect->objects[param->members[i].object_id];
6124 if (FAILED(ret = d3dx_create_param_eval(&effect->params, object->data, object->size, param->type,
6125 &param->members[i].param_eval, get_version_counter_ptr(effect),
6126 skip_constants, skip_constants_count)))
6127 break;
6131 return ret;
6134 static HRESULT d3dx_parse_resource(struct d3dx_effect *effect, const char *data, const char **ptr,
6135 const char **skip_constants, unsigned int skip_constants_count)
6137 unsigned int index, state_index, usage, element_index, technique_index;
6138 struct d3dx_parameter *param;
6139 struct d3dx_object *object;
6140 struct d3dx_state *state;
6141 HRESULT hr = E_FAIL;
6143 technique_index = read_u32(ptr);
6144 TRACE("technique_index: %u.\n", technique_index);
6146 index = read_u32(ptr);
6147 TRACE("index: %u.\n", index);
6149 element_index = read_u32(ptr);
6150 TRACE("element_index: %u.\n", element_index);
6152 state_index = read_u32(ptr);
6153 TRACE("state_index: %u.\n", state_index);
6155 usage = read_u32(ptr);
6156 TRACE("usage: %u.\n", usage);
6158 if (technique_index == 0xffffffff)
6160 struct d3dx_parameter *parameter;
6161 struct d3dx_sampler *sampler;
6163 if (index >= effect->params.count)
6165 FIXME("Index out of bounds: index %u >= parameter count %u.\n", index, effect->params.count);
6166 return E_FAIL;
6169 parameter = &effect->params.parameters[index].param;
6170 if (element_index != 0xffffffff)
6172 if (element_index >= parameter->element_count && parameter->element_count != 0)
6174 FIXME("Index out of bounds: element_index %u >= element_count %u.\n", element_index, parameter->element_count);
6175 return E_FAIL;
6178 if (parameter->element_count)
6179 parameter = &parameter->members[element_index];
6182 sampler = parameter->data;
6183 if (state_index >= sampler->state_count)
6185 FIXME("Index out of bounds: state_index %u >= state_count %u.\n", state_index, sampler->state_count);
6186 return E_FAIL;
6189 state = &sampler->states[state_index];
6191 else
6193 struct d3dx_technique *technique;
6194 struct d3dx_pass *pass;
6196 if (technique_index >= effect->technique_count)
6198 FIXME("Index out of bounds: technique_index %u >= technique_count %u.\n", technique_index,
6199 effect->technique_count);
6200 return E_FAIL;
6203 technique = &effect->techniques[technique_index];
6204 if (index >= technique->pass_count)
6206 FIXME("Index out of bounds: index %u >= pass_count %u.\n", index, technique->pass_count);
6207 return E_FAIL;
6210 pass = &technique->passes[index];
6211 if (state_index >= pass->state_count)
6213 FIXME("Index out of bounds: state_index %u >= state_count %u.\n", state_index, pass->state_count);
6214 return E_FAIL;
6217 state = &pass->states[state_index];
6220 TRACE("State operation %#x (%s).\n", state->operation, state_table[state->operation].name);
6221 param = &state->parameter;
6222 TRACE("Using object id %u.\n", param->object_id);
6223 object = &effect->objects[param->object_id];
6225 TRACE("Usage %u: class %s, type %s.\n", usage, debug_d3dxparameter_class(param->class),
6226 debug_d3dxparameter_type(param->type));
6227 switch (usage)
6229 case 0:
6230 switch (param->type)
6232 case D3DXPT_VERTEXSHADER:
6233 case D3DXPT_PIXELSHADER:
6234 state->type = ST_CONSTANT;
6235 if (FAILED(hr = d3dx9_copy_data(effect, param->object_id, ptr)))
6236 return hr;
6238 if (object->data)
6240 if (FAILED(hr = d3dx9_create_object(effect, object)))
6241 return hr;
6242 if (FAILED(hr = d3dx_create_param_eval(&effect->params, object->data, object->size, param->type,
6243 &param->param_eval, get_version_counter_ptr(effect),
6244 skip_constants, skip_constants_count)))
6245 return hr;
6247 break;
6249 case D3DXPT_BOOL:
6250 case D3DXPT_INT:
6251 case D3DXPT_FLOAT:
6252 case D3DXPT_STRING:
6253 state->type = ST_FXLC;
6254 if (FAILED(hr = d3dx9_copy_data(effect, param->object_id, ptr)))
6255 return hr;
6256 if (FAILED(hr = d3dx_create_param_eval(&effect->params, object->data, object->size, param->type,
6257 &param->param_eval, get_version_counter_ptr(effect), NULL, 0)))
6258 return hr;
6259 break;
6261 default:
6262 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(param->type));
6263 break;
6265 break;
6267 case 1:
6268 state->type = ST_PARAMETER;
6269 if (FAILED(hr = d3dx9_copy_data(effect, param->object_id, ptr)))
6270 return hr;
6272 TRACE("Looking for parameter %s.\n", debugstr_a(object->data));
6273 state->referenced_param = get_parameter_by_name(&effect->params, NULL, object->data);
6274 if (state->referenced_param)
6276 struct d3dx_parameter *refpar = state->referenced_param;
6278 TRACE("Mapping to parameter %p, having object id %u.\n", refpar, refpar->object_id);
6279 if (refpar->type == D3DXPT_VERTEXSHADER || refpar->type == D3DXPT_PIXELSHADER)
6281 struct d3dx_object *refobj = &effect->objects[refpar->object_id];
6283 if (!refpar->param_eval)
6285 if (FAILED(hr = d3dx_create_param_eval(&effect->params, refobj->data, refobj->size,
6286 refpar->type, &refpar->param_eval, get_version_counter_ptr(effect),
6287 skip_constants, skip_constants_count)))
6288 return hr;
6292 else
6294 FIXME("Referenced parameter %s not found.\n", (char *)object->data);
6295 return D3DXERR_INVALIDDATA;
6297 break;
6299 case 2:
6300 state->type = ST_ARRAY_SELECTOR;
6301 if (FAILED(hr = d3dx9_copy_data(effect, param->object_id, ptr)))
6302 return hr;
6303 hr = d3dx_parse_array_selector(effect, state, skip_constants, skip_constants_count);
6304 break;
6306 default:
6307 FIXME("Unknown usage %u.\n", usage);
6308 break;
6311 return hr;
6314 static BOOL param_set_top_level_param(void *top_level_param, struct d3dx_parameter *param)
6316 param->top_level_param = top_level_param;
6317 return FALSE;
6320 static HRESULT d3dx_parse_effect(struct d3dx_effect *effect, const char *data, UINT data_size,
6321 uint32_t start, const char **skip_constants, unsigned int skip_constants_count)
6323 unsigned int string_count, resource_count, params_count;
6324 const char *ptr = data + start;
6325 unsigned int i;
6326 HRESULT hr;
6328 params_count = read_u32(&ptr);
6329 TRACE("Parameter count: %u.\n", params_count);
6331 effect->technique_count = read_u32(&ptr);
6332 TRACE("Technique count: %u.\n", effect->technique_count);
6334 skip_u32_unknown(&ptr, 1);
6336 effect->object_count = read_u32(&ptr);
6337 TRACE("Object count: %u.\n", effect->object_count);
6339 effect->objects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6340 sizeof(*effect->objects) * effect->object_count);
6341 if (!effect->objects)
6343 ERR("Out of memory.\n");
6344 hr = E_OUTOFMEMORY;
6345 goto err_out;
6348 if (FAILED(hr = d3dx_init_parameters_store(&effect->params, params_count)))
6350 hr = E_OUTOFMEMORY;
6351 goto err_out;
6354 for (i = 0; i < effect->params.count; ++i)
6356 param_set_magic_number(&effect->params.parameters[i].param);
6357 hr = d3dx_parse_effect_parameter(effect, &effect->params.parameters[i], data, &ptr, effect->objects);
6358 if (hr != D3D_OK)
6360 WARN("Failed to parse parameter %u.\n", i);
6361 goto err_out;
6363 walk_parameter_tree(&effect->params.parameters[i].param, param_set_top_level_param, &effect->params.parameters[i]);
6364 add_param_to_tree(effect, &effect->params.parameters[i].param, NULL, 0, 0);
6367 if (effect->technique_count)
6369 effect->techniques = heap_alloc_zero(sizeof(*effect->techniques) * effect->technique_count);
6370 if (!effect->techniques)
6372 ERR("Out of memory.\n");
6373 hr = E_OUTOFMEMORY;
6374 goto err_out;
6377 for (i = 0; i < effect->technique_count; ++i)
6379 TRACE("Parsing technique %u.\n", i);
6380 hr = d3dx_parse_effect_technique(effect, &effect->techniques[i], data, &ptr, effect->objects);
6381 if (hr != D3D_OK)
6383 WARN("Failed to parse technique %u.\n", i);
6384 goto err_out;
6389 string_count = read_u32(&ptr);
6390 TRACE("String count: %u.\n", string_count);
6392 resource_count = read_u32(&ptr);
6393 TRACE("Resource count: %u.\n", resource_count);
6395 for (i = 0; i < string_count; ++i)
6397 unsigned int id;
6399 id = read_u32(&ptr);
6400 TRACE("id: %u.\n", id);
6402 if (FAILED(hr = d3dx9_copy_data(effect, id, &ptr)))
6403 goto err_out;
6405 if (effect->objects[id].data)
6407 if (FAILED(hr = d3dx9_create_object(effect, &effect->objects[id])))
6408 goto err_out;
6412 for (i = 0; i < resource_count; ++i)
6414 TRACE("parse resource %u.\n", i);
6416 hr = d3dx_parse_resource(effect, data, &ptr, skip_constants, skip_constants_count);
6417 if (hr != D3D_OK)
6419 WARN("Failed to parse resource %u.\n", i);
6420 goto err_out;
6424 for (i = 0; i < effect->params.count; ++i)
6426 if (FAILED(hr = d3dx_pool_sync_shared_parameter(effect->pool, &effect->params.parameters[i])))
6427 goto err_out;
6428 effect->params.parameters[i].version_counter = get_version_counter_ptr(effect);
6429 set_dirty(&effect->params.parameters[i].param);
6431 return D3D_OK;
6433 err_out:
6435 if (effect->techniques)
6437 for (i = 0; i < effect->technique_count; ++i)
6438 free_technique(&effect->techniques[i]);
6439 heap_free(effect->techniques);
6440 effect->techniques = NULL;
6443 d3dx_parameters_store_cleanup(&effect->params);
6445 if (effect->objects)
6447 for (i = 0; i < effect->object_count; ++i)
6449 free_object(&effect->objects[i]);
6451 HeapFree(GetProcessHeap(), 0, effect->objects);
6452 effect->objects = NULL;
6455 return hr;
6458 #define INITIAL_CONST_NAMES_SIZE 4
6460 static char *next_valid_constant_name(char **string)
6462 char *ret = *string;
6463 char *next;
6465 while (*ret && !isalpha(*ret) && *ret != '_')
6466 ++ret;
6467 if (!*ret)
6468 return NULL;
6470 next = ret + 1;
6471 while (isalpha(*next) || isdigit(*next) || *next == '_')
6472 ++next;
6473 if (*next)
6474 *next++ = 0;
6475 *string = next;
6476 return ret;
6479 static const char **parse_skip_constants_string(char *skip_constants_string, unsigned int *names_count)
6481 const char **names, **new_alloc;
6482 const char *name;
6483 char *s;
6484 unsigned int size = INITIAL_CONST_NAMES_SIZE;
6486 names = HeapAlloc(GetProcessHeap(), 0, sizeof(*names) * size);
6487 if (!names)
6488 return NULL;
6490 *names_count = 0;
6491 s = skip_constants_string;
6492 while ((name = next_valid_constant_name(&s)))
6494 if (*names_count == size)
6496 size *= 2;
6497 new_alloc = HeapReAlloc(GetProcessHeap(), 0, names, sizeof(*names) * size);
6498 if (!new_alloc)
6500 HeapFree(GetProcessHeap(), 0, names);
6501 return NULL;
6503 names = new_alloc;
6505 names[(*names_count)++] = name;
6507 new_alloc = HeapReAlloc(GetProcessHeap(), 0, names, *names_count * sizeof(*names));
6508 if (!new_alloc)
6509 return names;
6510 return new_alloc;
6513 static HRESULT d3dx9_effect_init_from_dxbc(struct d3dx_effect *effect,
6514 struct IDirect3DDevice9 *device, const char *data, SIZE_T data_size,
6515 unsigned int flags, struct ID3DXEffectPool *pool, const char *skip_constants_string)
6517 unsigned int skip_constants_count = 0;
6518 char *skip_constants_buffer = NULL;
6519 const char **skip_constants = NULL;
6520 const char *ptr = data;
6521 uint32_t tag, offset;
6522 unsigned int i, j;
6523 HRESULT hr;
6525 effect->ID3DXEffect_iface.lpVtbl = &ID3DXEffect_Vtbl;
6526 effect->ref = 1;
6528 effect->flags = flags;
6530 list_init(&effect->parameter_block_list);
6532 tag = read_u32(&ptr);
6533 TRACE("Tag: %#x.\n", tag);
6535 if (!(flags & D3DXFX_NOT_CLONEABLE))
6537 if (!(effect->source = malloc(data_size)))
6538 return E_OUTOFMEMORY;
6539 memcpy(effect->source, data, data_size);
6540 effect->source_size = data_size;
6543 if (pool)
6545 effect->pool = unsafe_impl_from_ID3DXEffectPool(pool);
6546 pool->lpVtbl->AddRef(pool);
6549 IDirect3DDevice9_AddRef(device);
6550 effect->device = device;
6552 if (skip_constants_string)
6554 if (!(flags & D3DXFX_NOT_CLONEABLE) && !(effect->skip_constants_string = strdup(skip_constants_string)))
6556 hr = E_OUTOFMEMORY;
6557 goto fail;
6560 skip_constants_buffer = HeapAlloc(GetProcessHeap(), 0,
6561 sizeof(*skip_constants_buffer) * (strlen(skip_constants_string) + 1));
6562 if (!skip_constants_buffer)
6564 hr = E_OUTOFMEMORY;
6565 goto fail;
6567 strcpy(skip_constants_buffer, skip_constants_string);
6569 if (!(skip_constants = parse_skip_constants_string(skip_constants_buffer, &skip_constants_count)))
6571 HeapFree(GetProcessHeap(), 0, skip_constants_buffer);
6572 hr = E_OUTOFMEMORY;
6573 goto fail;
6576 offset = read_u32(&ptr);
6577 TRACE("Offset: %#x.\n", offset);
6579 hr = d3dx_parse_effect(effect, ptr, data_size, offset, skip_constants, skip_constants_count);
6580 if (hr != D3D_OK)
6582 FIXME("Failed to parse effect.\n");
6583 HeapFree(GetProcessHeap(), 0, skip_constants_buffer);
6584 HeapFree(GetProcessHeap(), 0, skip_constants);
6585 goto fail;
6588 for (i = 0; i < skip_constants_count; ++i)
6590 struct d3dx_parameter *param;
6591 param = get_parameter_by_name(&effect->params, NULL, skip_constants[i]);
6592 if (param)
6594 for (j = 0; j < effect->technique_count; ++j)
6596 if (is_parameter_used(param, &effect->techniques[j]))
6598 WARN("skip_constants parameter %s is used in technique %u.\n",
6599 debugstr_a(skip_constants[i]), j);
6600 HeapFree(GetProcessHeap(), 0, skip_constants_buffer);
6601 HeapFree(GetProcessHeap(), 0, skip_constants);
6602 hr = D3DERR_INVALIDCALL;
6603 goto fail;
6607 else
6609 TRACE("skip_constants parameter %s not found.\n",
6610 debugstr_a(skip_constants[i]));
6614 HeapFree(GetProcessHeap(), 0, skip_constants_buffer);
6615 HeapFree(GetProcessHeap(), 0, skip_constants);
6617 /* initialize defaults - check because of unsupported ascii effects */
6618 if (effect->techniques)
6620 effect->active_technique = &effect->techniques[0];
6621 effect->active_pass = NULL;
6624 return D3D_OK;
6626 fail:
6627 if (effect->techniques)
6629 for (i = 0; i < effect->technique_count; ++i)
6630 free_technique(&effect->techniques[i]);
6631 heap_free(effect->techniques);
6634 if (effect->params.parameters)
6636 for (i = 0; i < effect->params.count; ++i)
6637 free_top_level_parameter(&effect->params.parameters[i]);
6638 heap_free(effect->params.parameters);
6641 if (effect->objects)
6643 for (i = 0; i < effect->object_count; ++i)
6644 free_object(&effect->objects[i]);
6645 heap_free(effect->objects);
6648 IDirect3DDevice9_Release(effect->device);
6649 if (pool)
6650 pool->lpVtbl->Release(pool);
6651 free(effect->source);
6652 free(effect->skip_constants_string);
6653 return hr;
6656 static HRESULT d3dx9_effect_init(struct d3dx_effect *effect, struct IDirect3DDevice9 *device,
6657 const char *data, SIZE_T data_size, const D3D_SHADER_MACRO *defines, ID3DInclude *include,
6658 UINT flags, ID3DBlob **errors, struct ID3DXEffectPool *pool, const char *skip_constants_string)
6660 #if D3DX_SDK_VERSION <= 36
6661 UINT compile_flags = D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY;
6662 #else
6663 UINT compile_flags = 0;
6664 #endif
6665 ID3DBlob *bytecode = NULL, *temp_errors = NULL;
6666 const char *ptr = data;
6667 unsigned int tag;
6668 HRESULT hr;
6670 TRACE("effect %p, device %p, data %p, data_size %Iu, defines %p, include %p, flags %#x, errors %p, "
6671 "pool %p, skip_constants %s.\n",
6672 effect, device, data, data_size, defines, include, flags, errors, pool,
6673 debugstr_a(skip_constants_string));
6675 tag = read_u32(&ptr);
6677 if (tag == d3dx9_effect_version(9, 1))
6678 return d3dx9_effect_init_from_dxbc(effect, device, data, data_size, flags, pool, skip_constants_string);
6680 TRACE("HLSL ASCII effect, trying to compile it.\n");
6681 compile_flags |= flags & ~(D3DXFX_NOT_CLONEABLE | D3DXFX_LARGEADDRESSAWARE);
6682 hr = D3DCompile(data, data_size, NULL, defines, include,
6683 NULL, "fx_2_0", compile_flags, 0, &bytecode, &temp_errors);
6684 if (FAILED(hr))
6686 WARN("Failed to compile ASCII effect.\n");
6687 if (bytecode)
6688 ID3D10Blob_Release(bytecode);
6689 if (temp_errors)
6691 const char *error_string = ID3D10Blob_GetBufferPointer(temp_errors);
6692 const char *string_ptr;
6694 while (*error_string)
6696 string_ptr = error_string;
6697 while (*string_ptr && *string_ptr != '\n' && *string_ptr != '\r'
6698 && string_ptr - error_string < 80)
6699 ++string_ptr;
6700 TRACE("%s\n", debugstr_an(error_string, string_ptr - error_string));
6701 error_string = string_ptr;
6702 while (*error_string == '\n' || *error_string == '\r')
6703 ++error_string;
6706 if (errors)
6707 *errors = temp_errors;
6708 else if (temp_errors)
6709 ID3D10Blob_Release(temp_errors);
6710 return hr;
6712 if (!bytecode)
6714 FIXME("No output from effect compilation.\n");
6715 return D3DERR_INVALIDCALL;
6717 if (errors)
6718 *errors = temp_errors;
6719 else if (temp_errors)
6720 ID3D10Blob_Release(temp_errors);
6722 hr = d3dx9_effect_init_from_dxbc(effect, device, ID3D10Blob_GetBufferPointer(bytecode),
6723 ID3D10Blob_GetBufferSize(bytecode), flags, pool, skip_constants_string);
6724 ID3D10Blob_Release(bytecode);
6725 return hr;
6728 HRESULT WINAPI D3DXCreateEffectEx(struct IDirect3DDevice9 *device, const void *srcdata, UINT srcdatalen,
6729 const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skip_constants, DWORD flags,
6730 struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilation_errors)
6732 struct d3dx_effect *object;
6733 HRESULT hr;
6735 TRACE("device %p, srcdata %p, srcdatalen %u, defines %p, include %p, "
6736 "skip_constants %p, flags %#lx, pool %p, effect %p, compilation_errors %p.\n",
6737 device, srcdata, srcdatalen, defines, include,
6738 skip_constants, flags, pool, effect, compilation_errors);
6740 if (compilation_errors)
6741 *compilation_errors = NULL;
6743 if (!device || !srcdata)
6744 return D3DERR_INVALIDCALL;
6746 if (!srcdatalen)
6747 return E_FAIL;
6749 /* Native dll allows effect to be null so just return D3D_OK after doing basic checks */
6750 if (!effect)
6751 return D3D_OK;
6753 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6754 if (!object)
6755 return E_OUTOFMEMORY;
6757 hr = d3dx9_effect_init(object, device, srcdata, srcdatalen, (const D3D_SHADER_MACRO *)defines,
6758 (ID3DInclude *)include, flags, (ID3DBlob **)compilation_errors, pool, skip_constants);
6759 if (FAILED(hr))
6761 WARN("Failed to create effect object, hr %#lx.\n", hr);
6762 return hr;
6765 *effect = &object->ID3DXEffect_iface;
6767 TRACE("Created ID3DXEffect %p\n", object);
6769 return D3D_OK;
6772 HRESULT WINAPI D3DXCreateEffect(struct IDirect3DDevice9 *device, const void *data, UINT data_size,
6773 const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags,
6774 struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
6776 TRACE("device %p, data %p, data_size %u, defines %p, include %p, flags %#lx, pool %p, "
6777 "effect %p, messages %p.\n", device, data, data_size, defines,
6778 include, flags, pool, effect, messages);
6780 return D3DXCreateEffectEx(device, data, data_size, defines, include, NULL, flags, pool, effect, messages);
6783 static HRESULT d3dx9_effect_compiler_init(struct ID3DXEffectCompilerImpl *compiler,
6784 const char *data, SIZE_T data_size, const D3D_SHADER_MACRO *defines, ID3DInclude *include,
6785 UINT eflags, ID3DBlob **messages)
6787 TRACE("compiler %p, data %p, data_size %Iu, defines %p, include %p, eflags %#x, messages %p.\n",
6788 compiler, data, data_size, defines, include, eflags, messages);
6790 compiler->ID3DXEffectCompiler_iface.lpVtbl = &ID3DXEffectCompiler_Vtbl;
6791 compiler->ref = 1;
6793 FIXME("ID3DXEffectCompiler implementation is only a stub.\n");
6795 return D3D_OK;
6798 HRESULT WINAPI D3DXCreateEffectCompiler(const char *data, UINT data_size, const D3DXMACRO *defines,
6799 ID3DXInclude *include, DWORD flags, ID3DXEffectCompiler **compiler, ID3DXBuffer **messages)
6801 struct ID3DXEffectCompilerImpl *object;
6802 HRESULT hr;
6804 TRACE("data %p, data_size %u, defines %p, include %p, flags %#lx, compiler %p, messages %p.\n",
6805 data, data_size, defines, include, flags, compiler, messages);
6807 if (!data || !compiler)
6809 WARN("Invalid arguments supplied\n");
6810 return D3DERR_INVALIDCALL;
6813 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6814 if (!object)
6815 return E_OUTOFMEMORY;
6817 hr = d3dx9_effect_compiler_init(object, data, data_size, (const D3D_SHADER_MACRO *)defines,
6818 (ID3DInclude *)include, flags, (ID3DBlob **)messages);
6819 if (FAILED(hr))
6821 WARN("Failed to initialize effect compiler\n");
6822 HeapFree(GetProcessHeap(), 0, object);
6823 return hr;
6826 *compiler = &object->ID3DXEffectCompiler_iface;
6828 TRACE("Created ID3DXEffectCompiler %p\n", object);
6830 return D3D_OK;
6833 /*** IUnknown methods ***/
6834 static HRESULT WINAPI d3dx_effect_pool_QueryInterface(ID3DXEffectPool *iface, REFIID riid, void **object)
6836 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
6838 if (IsEqualGUID(riid, &IID_IUnknown) ||
6839 IsEqualGUID(riid, &IID_ID3DXEffectPool))
6841 iface->lpVtbl->AddRef(iface);
6842 *object = iface;
6843 return S_OK;
6846 WARN("Interface %s not found\n", debugstr_guid(riid));
6848 return E_NOINTERFACE;
6851 static ULONG WINAPI d3dx_effect_pool_AddRef(ID3DXEffectPool *iface)
6853 struct d3dx_effect_pool *pool = impl_from_ID3DXEffectPool(iface);
6854 ULONG refcount = InterlockedIncrement(&pool->refcount);
6856 TRACE("%p increasing refcount to %lu.\n", pool, refcount);
6858 return refcount;
6861 static void free_effect_pool(struct d3dx_effect_pool *pool)
6863 unsigned int i;
6865 for (i = 0; i < pool->size; ++i)
6867 if (pool->shared_data[i].count)
6869 unsigned int j;
6871 WARN("Releasing pool with referenced parameters.\n");
6873 param_set_data_pointer(&pool->shared_data[i].parameters[0]->param, NULL, FALSE, TRUE);
6874 pool->shared_data[i].parameters[0]->shared_data = NULL;
6876 for (j = 1; j < pool->shared_data[i].count; ++j)
6878 walk_parameter_tree(&pool->shared_data[i].parameters[j]->param, param_zero_data_func, NULL);
6879 pool->shared_data[i].parameters[j]->shared_data = NULL;
6881 HeapFree(GetProcessHeap(), 0, pool->shared_data[i].parameters);
6884 HeapFree(GetProcessHeap(), 0, pool->shared_data);
6885 HeapFree(GetProcessHeap(), 0, pool);
6888 static ULONG WINAPI d3dx_effect_pool_Release(ID3DXEffectPool *iface)
6890 struct d3dx_effect_pool *pool = impl_from_ID3DXEffectPool(iface);
6891 ULONG refcount = InterlockedDecrement(&pool->refcount);
6893 TRACE("%p decreasing refcount to %lu.\n", pool, refcount);
6895 if (!refcount)
6896 free_effect_pool(pool);
6898 return refcount;
6901 static const struct ID3DXEffectPoolVtbl ID3DXEffectPool_Vtbl =
6903 /*** IUnknown methods ***/
6904 d3dx_effect_pool_QueryInterface,
6905 d3dx_effect_pool_AddRef,
6906 d3dx_effect_pool_Release
6909 static inline struct d3dx_effect_pool *unsafe_impl_from_ID3DXEffectPool(ID3DXEffectPool *iface)
6911 if (!iface)
6912 return NULL;
6914 assert(iface->lpVtbl == &ID3DXEffectPool_Vtbl);
6915 return impl_from_ID3DXEffectPool(iface);
6918 HRESULT WINAPI D3DXCreateEffectPool(ID3DXEffectPool **pool)
6920 struct d3dx_effect_pool *object;
6922 TRACE("pool %p.\n", pool);
6924 if (!pool)
6925 return D3DERR_INVALIDCALL;
6927 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6928 if (!object)
6929 return E_OUTOFMEMORY;
6931 object->ID3DXEffectPool_iface.lpVtbl = &ID3DXEffectPool_Vtbl;
6932 object->refcount = 1;
6934 *pool = &object->ID3DXEffectPool_iface;
6936 return S_OK;
6939 HRESULT WINAPI D3DXCreateEffectFromFileExW(struct IDirect3DDevice9 *device, const WCHAR *srcfile,
6940 const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skipconstants, DWORD flags,
6941 struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
6943 struct d3dx_include_from_file include_from_file;
6944 const void *buffer;
6945 unsigned int size;
6946 char *filename_a;
6947 HRESULT ret;
6949 TRACE("device %p, srcfile %s, defines %p, include %p, skipconstants %s, "
6950 "flags %#lx, pool %p, effect %p, messages %p.\n",
6951 device, debugstr_w(srcfile), defines, include, debugstr_a(skipconstants),
6952 flags, pool, effect, messages);
6954 if (!device || !srcfile)
6955 return D3DERR_INVALIDCALL;
6957 if (!include)
6959 include_from_file.ID3DXInclude_iface.lpVtbl = &d3dx_include_from_file_vtbl;
6960 include = &include_from_file.ID3DXInclude_iface;
6963 size = WideCharToMultiByte(CP_ACP, 0, srcfile, -1, NULL, 0, NULL, NULL);
6964 filename_a = heap_alloc(size);
6965 if (!filename_a)
6966 return E_OUTOFMEMORY;
6967 WideCharToMultiByte(CP_ACP, 0, srcfile, -1, filename_a, size, NULL, NULL);
6969 EnterCriticalSection(&from_file_mutex);
6970 ret = ID3DXInclude_Open(include, D3DXINC_LOCAL, filename_a, NULL, &buffer, &size);
6971 if (FAILED(ret))
6973 LeaveCriticalSection(&from_file_mutex);
6974 heap_free(filename_a);
6975 return D3DXERR_INVALIDDATA;
6978 ret = D3DXCreateEffectEx(device, buffer, size, defines, include, skipconstants, flags, pool,
6979 effect, messages);
6981 ID3DXInclude_Close(include, buffer);
6982 LeaveCriticalSection(&from_file_mutex);
6983 heap_free(filename_a);
6984 return ret;
6987 HRESULT WINAPI D3DXCreateEffectFromFileExA(struct IDirect3DDevice9 *device, const char *srcfile,
6988 const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skipconstants, DWORD flags,
6989 struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
6991 WCHAR *srcfileW;
6992 HRESULT ret;
6993 DWORD len;
6995 TRACE("device %p, srcfile %s, defines %p, include %p, skipconstants %s, "
6996 "flags %#lx, pool %p, effect %p, messages %p.\n",
6997 device, debugstr_a(srcfile), defines, include, debugstr_a(skipconstants),
6998 flags, pool, effect, messages);
7000 if (!srcfile)
7001 return D3DERR_INVALIDCALL;
7003 len = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0);
7004 srcfileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(*srcfileW));
7005 MultiByteToWideChar(CP_ACP, 0, srcfile, -1, srcfileW, len);
7007 ret = D3DXCreateEffectFromFileExW(device, srcfileW, defines, include, skipconstants, flags, pool, effect, messages);
7008 HeapFree(GetProcessHeap(), 0, srcfileW);
7010 return ret;
7013 HRESULT WINAPI D3DXCreateEffectFromFileW(struct IDirect3DDevice9 *device, const WCHAR *srcfile,
7014 const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags, struct ID3DXEffectPool *pool,
7015 struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
7017 TRACE("(void): relay\n");
7018 return D3DXCreateEffectFromFileExW(device, srcfile, defines, include, NULL, flags, pool,
7019 effect, messages);
7022 HRESULT WINAPI D3DXCreateEffectFromFileA(struct IDirect3DDevice9 *device, const char *srcfile,
7023 const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags, struct ID3DXEffectPool *pool,
7024 struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
7026 TRACE("(void): relay\n");
7027 return D3DXCreateEffectFromFileExA(device, srcfile, defines, include, NULL, flags, pool,
7028 effect, messages);
7031 HRESULT WINAPI D3DXCreateEffectFromResourceExW(struct IDirect3DDevice9 *device, HMODULE srcmodule,
7032 const WCHAR *srcresource, const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skipconstants,
7033 DWORD flags, struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
7035 HRSRC resinfo;
7036 void *buffer;
7037 DWORD size;
7039 TRACE("device %p, srcmodule %p, srcresource %s, defines %p, include %p, skipconstants %s, "
7040 "flags %#lx, pool %p, effect %p, messages %p.\n",
7041 device, srcmodule, debugstr_w(srcresource), defines, include, debugstr_a(skipconstants),
7042 flags, pool, effect, messages);
7044 if (!device)
7045 return D3DERR_INVALIDCALL;
7047 if (!(resinfo = FindResourceW(srcmodule, srcresource, (const WCHAR *)RT_RCDATA)))
7048 return D3DXERR_INVALIDDATA;
7050 if (FAILED(load_resource_into_memory(srcmodule, resinfo, &buffer, &size)))
7051 return D3DXERR_INVALIDDATA;
7053 return D3DXCreateEffectEx(device, buffer, size, defines, include,
7054 skipconstants, flags, pool, effect, messages);
7057 HRESULT WINAPI D3DXCreateEffectFromResourceExA(struct IDirect3DDevice9 *device, HMODULE srcmodule,
7058 const char *srcresource, const D3DXMACRO *defines, struct ID3DXInclude *include,
7059 const char *skipconstants, DWORD flags, struct ID3DXEffectPool *pool,
7060 struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
7062 HRSRC resinfo;
7063 void *buffer;
7064 DWORD size;
7066 TRACE("device %p, srcmodule %p, srcresource %s, defines %p, include %p, skipconstants %s, "
7067 "flags %#lx, pool %p, effect %p, messages %p.\n",
7068 device, srcmodule, debugstr_a(srcresource), defines, include, debugstr_a(skipconstants),
7069 flags, pool, effect, messages);
7071 if (!device)
7072 return D3DERR_INVALIDCALL;
7074 if (!(resinfo = FindResourceA(srcmodule, srcresource, (const char *)RT_RCDATA)))
7075 return D3DXERR_INVALIDDATA;
7077 if (FAILED(load_resource_into_memory(srcmodule, resinfo, &buffer, &size)))
7078 return D3DXERR_INVALIDDATA;
7080 return D3DXCreateEffectEx(device, buffer, size, defines, include,
7081 skipconstants, flags, pool, effect, messages);
7084 HRESULT WINAPI D3DXCreateEffectFromResourceW(struct IDirect3DDevice9 *device, HMODULE srcmodule,
7085 const WCHAR *srcresource, const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags,
7086 struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
7088 TRACE("(void): relay\n");
7089 return D3DXCreateEffectFromResourceExW(device, srcmodule, srcresource, defines, include, NULL,
7090 flags, pool, effect, messages);
7093 HRESULT WINAPI D3DXCreateEffectFromResourceA(struct IDirect3DDevice9 *device, HMODULE srcmodule,
7094 const char *srcresource, const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags,
7095 struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
7097 TRACE("(void): relay\n");
7098 return D3DXCreateEffectFromResourceExA(device, srcmodule, srcresource, defines, include, NULL,
7099 flags, pool, effect, messages);
7102 HRESULT WINAPI D3DXCreateEffectCompilerFromFileW(const WCHAR *srcfile, const D3DXMACRO *defines,
7103 ID3DXInclude *include, DWORD flags, ID3DXEffectCompiler **compiler, ID3DXBuffer **messages)
7105 void *buffer;
7106 HRESULT ret;
7107 DWORD size;
7109 TRACE("srcfile %s, defines %p, include %p, flags %#lx, compiler %p, messages %p.\n",
7110 debugstr_w(srcfile), defines, include, flags, compiler, messages);
7112 if (!srcfile)
7113 return D3DERR_INVALIDCALL;
7115 ret = map_view_of_file(srcfile, &buffer, &size);
7117 if (FAILED(ret))
7118 return D3DXERR_INVALIDDATA;
7120 ret = D3DXCreateEffectCompiler(buffer, size, defines, include, flags, compiler, messages);
7121 UnmapViewOfFile(buffer);
7123 return ret;
7126 HRESULT WINAPI D3DXCreateEffectCompilerFromFileA(const char *srcfile, const D3DXMACRO *defines,
7127 ID3DXInclude *include, DWORD flags, ID3DXEffectCompiler **compiler, ID3DXBuffer **messages)
7129 WCHAR *srcfileW;
7130 HRESULT ret;
7131 DWORD len;
7133 TRACE("srcfile %s, defines %p, include %p, flags %#lx, compiler %p, messages %p.\n",
7134 debugstr_a(srcfile), defines, include, flags, compiler, messages);
7136 if (!srcfile)
7137 return D3DERR_INVALIDCALL;
7139 len = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0);
7140 srcfileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(*srcfileW));
7141 MultiByteToWideChar(CP_ACP, 0, srcfile, -1, srcfileW, len);
7143 ret = D3DXCreateEffectCompilerFromFileW(srcfileW, defines, include, flags, compiler, messages);
7144 HeapFree(GetProcessHeap(), 0, srcfileW);
7146 return ret;
7149 HRESULT WINAPI D3DXCreateEffectCompilerFromResourceA(HMODULE srcmodule, const char *srcresource,
7150 const D3DXMACRO *defines, ID3DXInclude *include, DWORD flags,
7151 ID3DXEffectCompiler **compiler, ID3DXBuffer **messages)
7153 HRSRC resinfo;
7154 void *buffer;
7155 DWORD size;
7157 TRACE("srcmodule %p, srcresource %s, defines %p, include %p, flags %#lx, compiler %p, messages %p.\n",
7158 srcmodule, debugstr_a(srcresource), defines, include, flags, compiler, messages);
7160 if (!(resinfo = FindResourceA(srcmodule, srcresource, (const char *)RT_RCDATA)))
7161 return D3DXERR_INVALIDDATA;
7163 if (FAILED(load_resource_into_memory(srcmodule, resinfo, &buffer, &size)))
7164 return D3DXERR_INVALIDDATA;
7166 return D3DXCreateEffectCompiler(buffer, size, defines, include, flags, compiler, messages);
7169 HRESULT WINAPI D3DXCreateEffectCompilerFromResourceW(HMODULE srcmodule, const WCHAR *srcresource,
7170 const D3DXMACRO *defines, ID3DXInclude *include, DWORD flags,
7171 ID3DXEffectCompiler **compiler, ID3DXBuffer **messages)
7173 HRSRC resinfo;
7174 void *buffer;
7175 DWORD size;
7177 TRACE("srcmodule %p, srcresource %s, defines %p, include %p, flags %#lx, compiler %p, messages %p.\n",
7178 srcmodule, debugstr_w(srcresource), defines, include, flags, compiler, messages);
7180 if (!(resinfo = FindResourceW(srcmodule, srcresource, (const WCHAR *)RT_RCDATA)))
7181 return D3DXERR_INVALIDDATA;
7183 if (FAILED(load_resource_into_memory(srcmodule, resinfo, &buffer, &size)))
7184 return D3DXERR_INVALIDDATA;
7186 return D3DXCreateEffectCompiler(buffer, size, defines, include, flags, compiler, messages);
7189 HRESULT WINAPI D3DXDisassembleEffect(ID3DXEffect *effect, BOOL enable_color_code, ID3DXBuffer **disassembly)
7191 FIXME("(%p, %u, %p): stub\n", effect, enable_color_code, disassembly);
7193 return D3DXERR_INVALIDDATA;