wow64: In wow64_NtSetInformationToken forward TokenIntegrityLevel.
[wine.git] / dlls / d3dx9_36 / effect.c
blobea965ce789bd071a64a261c19eb4c735a5bf8eec
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_binary(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 free(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 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 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 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 free(param->members);
635 free(param->full_name);
636 free_parameter_data(param, child);
638 /* only the parent has to release name and semantic */
639 if (!element)
641 free(param->name);
642 free(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 free(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 free(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 free(pass->states);
682 pass->states = NULL;
685 free(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 free(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 free(technique->passes);
717 technique->passes = NULL;
720 free(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 free(block->buffer);
745 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 = calloc(store->count, sizeof(*store->parameters))))
762 return E_OUTOFMEMORY;
764 return S_OK;
767 void d3dx_parameters_store_cleanup(struct d3dx_parameters_store *store)
769 unsigned int i;
771 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 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 free(effect->techniques);
806 if (effect->objects)
808 for (i = 0; i < effect->object_count; ++i)
809 free_object(&effect->objects[i]);
810 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 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 free(*param_data);
908 *param_data = strdup(string);
909 if (!*param_data)
911 ERR("Out of memory.\n");
912 return E_OUTOFMEMORY;
914 return D3D_OK;
917 static HRESULT set_value(struct d3dx_parameter *param, const void *data, unsigned int bytes,
918 void *dst_data)
920 unsigned int i, count;
922 bytes = min(bytes, param->bytes);
923 count = min(param->element_count ? param->element_count : 1, bytes / sizeof(void *));
925 switch (param->type)
927 case D3DXPT_TEXTURE:
928 case D3DXPT_TEXTURE1D:
929 case D3DXPT_TEXTURE2D:
930 case D3DXPT_TEXTURE3D:
931 case D3DXPT_TEXTURECUBE:
932 for (i = 0; i < count; ++i)
934 IUnknown *old_texture = ((IUnknown **)dst_data)[i];
935 IUnknown *new_texture = ((IUnknown **)data)[i];
937 if (new_texture == old_texture)
938 continue;
940 if (new_texture)
941 IUnknown_AddRef(new_texture);
942 if (old_texture)
943 IUnknown_Release(old_texture);
945 /* fallthrough */
946 case D3DXPT_VOID:
947 case D3DXPT_BOOL:
948 case D3DXPT_INT:
949 case D3DXPT_FLOAT:
950 TRACE("Copy %u bytes.\n", bytes);
951 memcpy(dst_data, data, bytes);
952 break;
954 case D3DXPT_STRING:
956 HRESULT hr;
958 for (i = 0; i < count; ++i)
959 if (FAILED(hr = set_string(&((char **)dst_data)[i], ((const char **)data)[i])))
960 return hr;
961 break;
964 default:
965 FIXME("Unhandled type %s.\n", debug_d3dxparameter_type(param->type));
966 break;
969 return D3D_OK;
972 static struct d3dx_parameter *get_parameter_element_by_name(struct d3dx_parameters_store *store,
973 struct d3dx_parameter *parameter, const char *name)
975 UINT element;
976 struct d3dx_parameter *temp_parameter;
977 const char *part;
979 TRACE("parameter %p, name %s\n", parameter, debugstr_a(name));
981 if (!name || !*name) return NULL;
983 element = atoi(name);
984 part = strchr(name, ']') + 1;
986 /* check for empty [] && element range */
987 if ((part - name) > 1 && parameter->element_count > element)
989 temp_parameter = &parameter->members[element];
991 switch (*part++)
993 case '.':
994 return get_parameter_by_name(store, temp_parameter, part);
996 case '\0':
997 TRACE("Returning parameter %p\n", temp_parameter);
998 return temp_parameter;
1000 default:
1001 FIXME("Unhandled case \"%c\"\n", *--part);
1002 break;
1006 TRACE("Parameter not found\n");
1007 return NULL;
1010 static struct d3dx_parameter *get_annotation_by_name(struct d3dx_effect *effect, unsigned int count,
1011 struct d3dx_parameter *annotations, const char *name)
1013 UINT i, length;
1014 struct d3dx_parameter *temp_parameter;
1015 const char *part;
1017 TRACE("count %u, annotations %p, name %s\n", count, annotations, debugstr_a(name));
1019 if (!name || !*name) return NULL;
1021 length = strcspn( name, "[.@" );
1022 part = name + length;
1024 for (i = 0; i < count; ++i)
1026 temp_parameter = &annotations[i];
1028 if (!strcmp(temp_parameter->name, name))
1030 TRACE("Returning annotation %p\n", temp_parameter);
1031 return temp_parameter;
1033 else if (strlen(temp_parameter->name) == length && !strncmp(temp_parameter->name, name, length))
1035 switch (*part++)
1037 case '.':
1038 return get_parameter_by_name(&effect->params, temp_parameter, part);
1040 case '[':
1041 return get_parameter_element_by_name(&effect->params, temp_parameter, part);
1043 default:
1044 FIXME("Unhandled case \"%c\"\n", *--part);
1045 break;
1050 TRACE("Annotation not found\n");
1051 return NULL;
1054 struct d3dx_parameter *get_parameter_by_name(struct d3dx_parameters_store *store,
1055 struct d3dx_parameter *parameter, const char *name)
1057 struct d3dx_parameter *temp_parameter;
1058 unsigned int name_len, param_name_len;
1059 unsigned int i, count, length;
1060 struct wine_rb_entry *entry;
1061 unsigned int full_name_size;
1062 const char *part;
1063 char *full_name;
1065 TRACE("store %p, parameter %p, name %s.\n", store, parameter, debugstr_a(name));
1067 if (!name || !*name) return NULL;
1069 if (!parameter)
1071 if ((entry = wine_rb_get(&store->tree, name)))
1072 return WINE_RB_ENTRY_VALUE(entry, struct d3dx_parameter, rb_entry);
1073 return NULL;
1076 if (parameter->full_name)
1078 name_len = strlen(name);
1079 param_name_len = strlen(parameter->full_name);
1080 full_name_size = name_len + param_name_len + 2;
1081 if (store->full_name_tmp_size < full_name_size)
1083 if (!(full_name = realloc(store->full_name_tmp, full_name_size)))
1085 ERR("Out of memory.\n");
1086 return NULL;
1088 store->full_name_tmp = full_name;
1089 store->full_name_tmp_size = full_name_size;
1091 else
1093 full_name = store->full_name_tmp;
1095 memcpy(full_name, parameter->full_name, param_name_len);
1096 full_name[param_name_len] = '.';
1097 memcpy(full_name + param_name_len + 1, name, name_len);
1098 full_name[param_name_len + 1 + name_len] = 0;
1100 if ((entry = wine_rb_get(&store->tree, full_name)))
1101 return WINE_RB_ENTRY_VALUE(entry, struct d3dx_parameter, rb_entry);
1102 return NULL;
1105 /* Pass / technique annotations are not stored in the parameters tree,
1106 * do a linear search. */
1107 count = parameter->member_count;
1109 length = strcspn( name, "[." );
1110 part = name + length;
1112 for (i = 0; i < count; i++)
1114 temp_parameter = &parameter->members[i];
1116 if (!strcmp(temp_parameter->name, name))
1118 TRACE("Returning parameter %p\n", temp_parameter);
1119 return temp_parameter;
1121 else if (strlen(temp_parameter->name) == length && !strncmp(temp_parameter->name, name, length))
1123 switch (*part++)
1125 case '.':
1126 return get_parameter_by_name(store, temp_parameter, part);
1128 case '[':
1129 return get_parameter_element_by_name(store, temp_parameter, part);
1131 default:
1132 FIXME("Unhandled case \"%c\"\n", *--part);
1133 break;
1138 TRACE("Parameter not found\n");
1139 return NULL;
1142 static inline DWORD d3dx9_effect_version(DWORD major, DWORD minor)
1144 return (0xfeff0000 | ((major) << 8) | (minor));
1147 static HRESULT d3dx9_get_param_value_ptr(struct d3dx_pass *pass, struct d3dx_state *state,
1148 void **param_value, struct d3dx_parameter **out_param,
1149 BOOL update_all, BOOL *param_dirty)
1151 struct d3dx_parameter *param = &state->parameter;
1153 *param_value = NULL;
1154 *out_param = NULL;
1155 *param_dirty = FALSE;
1157 switch (state->type)
1159 case ST_PARAMETER:
1160 param = state->referenced_param;
1161 *param_dirty = is_param_dirty(param, pass->update_version);
1162 /* fallthrough */
1163 case ST_CONSTANT:
1164 *out_param = param;
1165 *param_value = param->data;
1166 return D3D_OK;
1167 case ST_ARRAY_SELECTOR:
1169 unsigned int array_idx;
1170 static const struct d3dx_parameter array_idx_param =
1171 {"", NULL, NULL, NULL, NULL, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 0, 0, 0, sizeof(array_idx)};
1172 HRESULT hr;
1173 struct d3dx_parameter *ref_param, *selected_param;
1175 if (!param->param_eval)
1177 FIXME("Preshader structure is null.\n");
1178 return D3DERR_INVALIDCALL;
1180 /* We override with the update_version of the pass because we want
1181 * to force index recomputation and check for out of bounds. */
1182 if (is_param_eval_input_dirty(param->param_eval, pass->update_version))
1184 if (FAILED(hr = d3dx_evaluate_parameter(param->param_eval, &array_idx_param, &array_idx)))
1185 return hr;
1187 else
1189 array_idx = state->index;
1191 ref_param = state->referenced_param;
1192 TRACE("Array index %u, stored array index %u, element_count %u.\n", array_idx, state->index,
1193 ref_param->element_count);
1194 /* According to the tests, native d3dx handles the case of array index evaluated to -1
1195 * in a specific way, always selecting first array element and not returning error. */
1196 if (array_idx == ~0u)
1198 WARN("Array index is -1, setting to 0.\n");
1199 array_idx = 0;
1202 if (array_idx >= ref_param->element_count)
1204 WARN("Computed array index %u is larger than array size %u.\n",
1205 array_idx, ref_param->element_count);
1206 return E_FAIL;
1208 selected_param = &ref_param->members[array_idx];
1209 *param_dirty = state->index != array_idx || is_param_dirty(selected_param, pass->update_version);
1210 state->index = array_idx;
1212 *param_value = selected_param->data;
1213 *out_param = selected_param;
1214 return D3D_OK;
1216 case ST_FXLC:
1217 if (param->param_eval)
1219 *out_param = param;
1220 *param_value = param->data;
1221 /* We check with the update_version of the pass because the
1222 * same preshader might be used by both the vertex and the
1223 * pixel shader (that can happen e.g. for sampler states). */
1224 if (update_all || is_param_eval_input_dirty(param->param_eval, pass->update_version))
1226 *param_dirty = TRUE;
1227 return d3dx_evaluate_parameter(param->param_eval, param, *param_value);
1229 else
1230 return D3D_OK;
1232 else
1234 FIXME("No preshader for FXLC parameter.\n");
1235 return D3DERR_INVALIDCALL;
1238 return E_NOTIMPL;
1241 static unsigned int get_annotation_from_object(struct d3dx_effect *effect, D3DXHANDLE object,
1242 struct d3dx_parameter **annotations)
1244 struct d3dx_parameter *param = get_valid_parameter(effect, object);
1245 struct d3dx_pass *pass = get_valid_pass(effect, object);
1246 struct d3dx_technique *technique = get_valid_technique(effect, object);
1248 if (pass)
1250 *annotations = pass->annotations;
1251 return pass->annotation_count;
1253 else if (technique)
1255 *annotations = technique->annotations;
1256 return technique->annotation_count;
1258 else if (param)
1260 if (is_top_level_parameter(param))
1262 struct d3dx_top_level_parameter *top_param
1263 = top_level_parameter_from_parameter(param);
1265 *annotations = top_param->annotations;
1266 return top_param->annotation_count;
1268 else
1270 *annotations = NULL;
1271 return 0;
1274 else
1276 FIXME("Functions are not handled, yet!\n");
1277 return 0;
1281 static BOOL walk_parameter_tree(struct d3dx_parameter *param, walk_parameter_dep_func param_func,
1282 void *data)
1284 unsigned int i;
1285 unsigned int member_count;
1287 if (param_func(data, param))
1288 return TRUE;
1290 member_count = param->element_count ? param->element_count : param->member_count;
1291 for (i = 0; i < member_count; ++i)
1293 if (walk_parameter_tree(&param->members[i], param_func, data))
1294 return TRUE;
1296 return FALSE;
1299 static ULONG64 *get_version_counter_ptr(struct d3dx_effect *effect)
1301 return effect->pool ? &effect->pool->version_counter : &effect->version_counter;
1304 static ULONG64 next_effect_update_version(struct d3dx_effect *effect)
1306 return next_update_version(get_version_counter_ptr(effect));
1309 static void *record_parameter(struct d3dx_effect *effect, struct d3dx_parameter *param, unsigned int bytes)
1311 struct d3dx_parameter_block *block = effect->current_parameter_block;
1312 struct d3dx_recorded_parameter new_record, *record;
1313 unsigned int new_size, alloc_size;
1315 new_record.param = param;
1316 new_record.bytes = bytes;
1317 new_size = block->offset + get_recorded_parameter_size(&new_record);
1319 if (new_size > block->size)
1321 BYTE *new_alloc;
1323 alloc_size = max(block->size * 2, max(new_size, INITIAL_PARAM_BLOCK_SIZE));
1324 new_alloc = realloc(block->buffer, alloc_size);
1325 if (!new_alloc)
1327 ERR("Out of memory.\n");
1328 return param->data;
1330 /* Data update functions may want to free some references upon setting value. */
1331 memset(new_alloc + block->size, 0, alloc_size - block->size);
1333 block->size = alloc_size;
1334 block->buffer = new_alloc;
1336 record = (struct d3dx_recorded_parameter *)(block->buffer + block->offset);
1337 *record = new_record;
1338 block->offset = new_size;
1339 return record + 1;
1342 static void set_dirty(struct d3dx_parameter *param)
1344 struct d3dx_top_level_parameter *top_param = param->top_level_param;
1345 struct d3dx_shared_data *shared_data;
1346 ULONG64 new_update_version;
1348 /* This is true for annotations. */
1349 if (!top_param)
1350 return;
1352 new_update_version = next_update_version(top_param->version_counter);
1353 if ((shared_data = top_param->shared_data))
1354 shared_data->update_version = new_update_version;
1355 else
1356 top_param->update_version = new_update_version;
1359 static void *param_get_data_and_dirtify(struct d3dx_effect *effect, struct d3dx_parameter *param,
1360 unsigned int bytes, BOOL value_changed)
1362 assert(bytes <= param->bytes);
1364 if (value_changed && !effect->current_parameter_block)
1365 set_dirty(param);
1367 return effect->current_parameter_block ? record_parameter(effect, param, bytes) : param->data;
1370 static void d3dx9_set_light_parameter(enum LIGHT_TYPE op, D3DLIGHT9 *light, void *value)
1372 static const struct
1374 unsigned int offset;
1375 const char *name;
1377 light_tbl[] =
1379 {FIELD_OFFSET(D3DLIGHT9, Type), "LC_TYPE"},
1380 {FIELD_OFFSET(D3DLIGHT9, Diffuse), "LT_DIFFUSE"},
1381 {FIELD_OFFSET(D3DLIGHT9, Specular), "LT_SPECULAR"},
1382 {FIELD_OFFSET(D3DLIGHT9, Ambient), "LT_AMBIENT"},
1383 {FIELD_OFFSET(D3DLIGHT9, Position), "LT_POSITION"},
1384 {FIELD_OFFSET(D3DLIGHT9, Direction), "LT_DIRECTION"},
1385 {FIELD_OFFSET(D3DLIGHT9, Range), "LT_RANGE"},
1386 {FIELD_OFFSET(D3DLIGHT9, Falloff), "LT_FALLOFF"},
1387 {FIELD_OFFSET(D3DLIGHT9, Attenuation0), "LT_ATTENUATION0"},
1388 {FIELD_OFFSET(D3DLIGHT9, Attenuation1), "LT_ATTENUATION1"},
1389 {FIELD_OFFSET(D3DLIGHT9, Attenuation2), "LT_ATTENUATION2"},
1390 {FIELD_OFFSET(D3DLIGHT9, Theta), "LT_THETA"},
1391 {FIELD_OFFSET(D3DLIGHT9, Phi), "LT_PHI"}
1393 switch (op)
1395 case LT_TYPE:
1396 TRACE("LT_TYPE %u.\n", *(D3DLIGHTTYPE *)value);
1397 light->Type = *(D3DLIGHTTYPE *)value;
1398 break;
1399 case LT_DIFFUSE:
1400 case LT_SPECULAR:
1401 case LT_AMBIENT:
1403 D3DCOLORVALUE c = *(D3DCOLORVALUE *)value;
1405 TRACE("%s (%.8e %.8e %.8e %.8e).\n", light_tbl[op].name, c.r, c.g, c.b, c.a);
1406 *(D3DCOLORVALUE *)((BYTE *)light + light_tbl[op].offset) = c;
1407 break;
1409 case LT_POSITION:
1410 case LT_DIRECTION:
1412 D3DVECTOR v = *(D3DVECTOR *)value;
1414 TRACE("%s (%.8e %.8e %.8e).\n", light_tbl[op].name, v.x, v.y, v.z);
1415 *(D3DVECTOR *)((BYTE *)light + light_tbl[op].offset) = v;
1416 break;
1418 case LT_RANGE:
1419 case LT_FALLOFF:
1420 case LT_ATTENUATION0:
1421 case LT_ATTENUATION1:
1422 case LT_ATTENUATION2:
1423 case LT_THETA:
1424 case LT_PHI:
1426 float v = *(float *)value;
1427 TRACE("%s %.8e.\n", light_tbl[op].name, v);
1428 *(float *)((BYTE *)light + light_tbl[op].offset) = v;
1429 break;
1431 default:
1432 WARN("Unknown light parameter %u.\n", op);
1433 break;
1437 static void d3dx9_set_material_parameter(enum MATERIAL_TYPE op, D3DMATERIAL9 *material, void *value)
1439 static const struct
1441 unsigned int offset;
1442 const char *name;
1444 material_tbl[] =
1446 {FIELD_OFFSET(D3DMATERIAL9, Diffuse), "MT_DIFFUSE"},
1447 {FIELD_OFFSET(D3DMATERIAL9, Ambient), "MT_AMBIENT"},
1448 {FIELD_OFFSET(D3DMATERIAL9, Specular), "MT_SPECULAR"},
1449 {FIELD_OFFSET(D3DMATERIAL9, Emissive), "MT_EMISSIVE"},
1450 {FIELD_OFFSET(D3DMATERIAL9, Power), "MT_POWER"}
1453 switch (op)
1455 case MT_POWER:
1457 float v = *(float *)value;
1459 TRACE("%s %.8e.\n", material_tbl[op].name, v);
1460 material->Power = v;
1461 break;
1463 case MT_DIFFUSE:
1464 case MT_AMBIENT:
1465 case MT_SPECULAR:
1466 case MT_EMISSIVE:
1468 D3DCOLORVALUE c = *(D3DCOLORVALUE *)value;
1470 TRACE("%s, value (%.8e %.8e %.8e %.8e).\n", material_tbl[op].name, c.r, c.g, c.b, c.a);
1471 *(D3DCOLORVALUE *)((BYTE *)material + material_tbl[op].offset) = c;
1472 break;
1474 default:
1475 WARN("Unknown material parameter %u.\n", op);
1476 break;
1480 static HRESULT d3dx_set_shader_const_state(struct d3dx_effect *effect, enum SHADER_CONSTANT_TYPE op, UINT index,
1481 struct d3dx_parameter *param, void *value_ptr)
1483 static const struct
1485 D3DXPARAMETER_TYPE type;
1486 UINT elem_size;
1487 const char *name;
1489 const_tbl[] =
1491 {D3DXPT_FLOAT, sizeof(float) * 4, "SCT_VSFLOAT"},
1492 {D3DXPT_BOOL, sizeof(BOOL), "SCT_VSBOOL"},
1493 {D3DXPT_INT, sizeof(int) * 4, "SCT_VSINT"},
1494 {D3DXPT_FLOAT, sizeof(float) * 4, "SCT_PSFLOAT"},
1495 {D3DXPT_BOOL, sizeof(BOOL), "SCT_PSBOOL"},
1496 {D3DXPT_INT, sizeof(int) * 4, "SCT_PSINT"},
1499 BOOL is_heap_buffer = FALSE;
1500 unsigned int element_count;
1501 void *buffer = value_ptr;
1502 D3DXVECTOR4 value;
1503 HRESULT ret;
1505 assert(op < ARRAY_SIZE(const_tbl));
1506 element_count = param->bytes / const_tbl[op].elem_size;
1507 TRACE("%s, index %u, element_count %u.\n", const_tbl[op].name, index, element_count);
1508 if (param->type != const_tbl[op].type)
1510 FIXME("Unexpected param type %u.\n", param->type);
1511 return D3DERR_INVALIDCALL;
1514 if (param->bytes % const_tbl[op].elem_size || element_count > 1)
1516 unsigned int param_data_size;
1518 TRACE("Parameter size %u, rows %u, cols %u.\n", param->bytes, param->rows, param->columns);
1520 if (param->bytes % const_tbl[op].elem_size)
1521 ++element_count;
1522 if (element_count > 1)
1524 WARN("Setting %u elements.\n", element_count);
1525 buffer = calloc(element_count, const_tbl[op].elem_size);
1526 if (!buffer)
1528 ERR("Out of memory.\n");
1529 return E_OUTOFMEMORY;
1531 is_heap_buffer = TRUE;
1533 else
1535 assert(const_tbl[op].elem_size <= sizeof(value));
1536 buffer = &value;
1538 param_data_size = min(param->bytes, const_tbl[op].elem_size);
1539 memcpy(buffer, value_ptr, param_data_size);
1542 switch (op)
1544 case SCT_VSFLOAT:
1545 ret = SET_D3D_STATE(effect, SetVertexShaderConstantF, index, (const float *)buffer, element_count);
1546 break;
1547 case SCT_VSBOOL:
1548 ret = SET_D3D_STATE(effect, SetVertexShaderConstantB, index, (const BOOL *)buffer, element_count);
1549 break;
1550 case SCT_VSINT:
1551 ret = SET_D3D_STATE(effect, SetVertexShaderConstantI, index, (const int *)buffer, element_count);
1552 break;
1553 case SCT_PSFLOAT:
1554 ret = SET_D3D_STATE(effect, SetPixelShaderConstantF, index, (const float *)buffer, element_count);
1555 break;
1556 case SCT_PSBOOL:
1557 ret = SET_D3D_STATE(effect, SetPixelShaderConstantB, index, (const BOOL *)buffer, element_count);
1558 break;
1559 case SCT_PSINT:
1560 ret = SET_D3D_STATE(effect, SetPixelShaderConstantI, index, (const int *)buffer, element_count);
1561 break;
1562 default:
1563 ret = D3DERR_INVALIDCALL;
1564 break;
1567 if (is_heap_buffer)
1568 free(buffer);
1570 return ret;
1573 static HRESULT d3dx9_apply_state(struct d3dx_effect *effect, struct d3dx_pass *pass,
1574 struct d3dx_state *state, unsigned int parent_index, BOOL update_all);
1576 static HRESULT d3dx_set_shader_constants(struct d3dx_effect *effect, struct d3dx_pass *pass,
1577 struct d3dx_parameter *param, BOOL vs, BOOL update_all)
1579 HRESULT hr, ret;
1580 struct d3dx_parameter **params;
1581 D3DXCONSTANT_DESC *cdesc;
1582 unsigned int parameters_count;
1583 unsigned int i, j;
1585 if (!param->param_eval)
1587 FIXME("param_eval structure is null.\n");
1588 return D3DERR_INVALIDCALL;
1590 if (FAILED(hr = d3dx_param_eval_set_shader_constants(effect->manager, effect->device,
1591 param->param_eval, update_all)))
1592 return hr;
1593 params = param->param_eval->shader_inputs.inputs_param;
1594 cdesc = param->param_eval->shader_inputs.inputs;
1595 parameters_count = param->param_eval->shader_inputs.input_count;
1596 ret = D3D_OK;
1597 for (i = 0; i < parameters_count; ++i)
1599 if (params[i] && params[i]->class == D3DXPC_OBJECT && is_param_type_sampler(params[i]->type))
1601 struct d3dx_sampler *sampler;
1602 unsigned int sampler_idx;
1604 for (sampler_idx = 0; sampler_idx < cdesc[i].RegisterCount; ++sampler_idx)
1606 sampler = params[i]->element_count ? params[i]->members[sampler_idx].data : params[i]->data;
1607 TRACE("sampler %s, register index %u, state count %u.\n", debugstr_a(params[i]->name),
1608 cdesc[i].RegisterIndex, sampler->state_count);
1609 for (j = 0; j < sampler->state_count; ++j)
1611 if (FAILED(hr = d3dx9_apply_state(effect, pass, &sampler->states[j],
1612 cdesc[i].RegisterIndex + sampler_idx + (vs ? D3DVERTEXTEXTURESAMPLER0 : 0),
1613 update_all)))
1614 ret = hr;
1619 return ret;
1622 static HRESULT d3dx9_apply_state(struct d3dx_effect *effect, struct d3dx_pass *pass,
1623 struct d3dx_state *state, unsigned int parent_index, BOOL update_all)
1625 struct d3dx_parameter *param;
1626 void *param_value;
1627 BOOL param_dirty;
1628 HRESULT hr;
1630 TRACE("operation %u, index %u, type %u.\n", state->operation, state->index, state->type);
1632 if (FAILED(hr = d3dx9_get_param_value_ptr(pass, state, &param_value, &param,
1633 update_all, &param_dirty)))
1635 if (!update_all && hr == E_FAIL)
1637 /* Native d3dx9 returns D3D_OK from CommitChanges() involving
1638 * out of bounds array access and does not touch the affected
1639 * states. */
1640 WARN("Returning D3D_OK on out of bounds array access.\n");
1641 return D3D_OK;
1643 return hr;
1646 if (!(update_all || param_dirty
1647 || state_table[state->operation].class == SC_VERTEXSHADER
1648 || state_table[state->operation].class == SC_PIXELSHADER
1649 || state_table[state->operation].class == SC_SETSAMPLER))
1650 return D3D_OK;
1652 switch (state_table[state->operation].class)
1654 case SC_RENDERSTATE:
1655 TRACE("%s, operation %u, value %lu.\n", state_table[state->operation].name,
1656 state_table[state->operation].op, *(DWORD *)param_value);
1657 return SET_D3D_STATE(effect, SetRenderState, state_table[state->operation].op, *(DWORD *)param_value);
1658 case SC_FVF:
1659 TRACE("%s, value %#lx.\n", state_table[state->operation].name, *(DWORD *)param_value);
1660 return SET_D3D_STATE(effect, SetFVF, *(DWORD *)param_value);
1661 case SC_TEXTURE:
1663 UINT unit;
1665 unit = parent_index == ~0u ? state->index : parent_index;
1666 TRACE("%s, unit %u, value %p.\n", state_table[state->operation].name, unit,
1667 *(IDirect3DBaseTexture9 **)param_value);
1668 return SET_D3D_STATE(effect, SetTexture, unit, *(IDirect3DBaseTexture9 **)param_value);
1670 case SC_TEXTURESTAGE:
1671 TRACE("%s, stage %u, value %lu.\n", state_table[state->operation].name, state->index, *(DWORD *)param_value);
1672 return SET_D3D_STATE(effect, SetTextureStageState, state->index,
1673 state_table[state->operation].op, *(DWORD *)param_value);
1674 case SC_SETSAMPLER:
1676 struct d3dx_sampler *sampler;
1677 HRESULT ret, hr;
1678 unsigned int i;
1680 sampler = (struct d3dx_sampler *)param_value;
1681 TRACE("%s, sampler %u, applying %u states.\n", state_table[state->operation].name, state->index,
1682 sampler->state_count);
1683 ret = D3D_OK;
1684 for (i = 0; i < sampler->state_count; i++)
1686 if (FAILED(hr = d3dx9_apply_state(effect, pass, &sampler->states[i], state->index, update_all)))
1687 ret = hr;
1689 return ret;
1691 case SC_SAMPLERSTATE:
1693 UINT sampler;
1695 sampler = parent_index == ~0u ? state->index : parent_index;
1696 TRACE("%s, sampler %u, value %lu.\n", state_table[state->operation].name, sampler, *(DWORD *)param_value);
1697 return SET_D3D_STATE(effect, SetSamplerState, sampler, state_table[state->operation].op,
1698 *(DWORD *)param_value);
1700 case SC_VERTEXSHADER:
1701 TRACE("%s, shader %p.\n", state_table[state->operation].name, *(IDirect3DVertexShader9 **)param_value);
1702 if ((update_all || param_dirty)
1703 && FAILED(hr = SET_D3D_STATE(effect, SetVertexShader,
1704 *(IDirect3DVertexShader9 **)param_value)))
1705 ERR("Could not set vertex shader, hr %#lx.\n", hr);
1706 else if (*(IDirect3DVertexShader9 **)param_value)
1707 hr = d3dx_set_shader_constants(effect, pass, param, TRUE, update_all || param_dirty);
1708 return hr;
1709 case SC_PIXELSHADER:
1710 TRACE("%s, shader %p.\n", state_table[state->operation].name, *(IDirect3DPixelShader9 **)param_value);
1711 if ((update_all || param_dirty)
1712 && FAILED(hr = SET_D3D_STATE(effect, SetPixelShader,
1713 *(IDirect3DPixelShader9 **)param_value)))
1714 ERR("Could not set pixel shader, hr %#lx.\n", hr);
1715 else if (*(IDirect3DPixelShader9 **)param_value)
1716 hr = d3dx_set_shader_constants(effect, pass, param, FALSE, update_all || param_dirty);
1717 return hr;
1718 case SC_TRANSFORM:
1719 TRACE("%s, state %u.\n", state_table[state->operation].name, state->index);
1720 return SET_D3D_STATE(effect, SetTransform, state_table[state->operation].op + state->index,
1721 (D3DMATRIX *)param_value);
1722 case SC_LIGHTENABLE:
1723 TRACE("%s, index %u, value %u.\n", state_table[state->operation].name, state->index, *(BOOL *)param_value);
1724 return SET_D3D_STATE(effect, LightEnable, state->index, *(BOOL *)param_value);
1725 case SC_LIGHT:
1727 TRACE("%s, index %u, op %u.\n", state_table[state->operation].name, state->index,
1728 state_table[state->operation].op);
1729 d3dx9_set_light_parameter(state_table[state->operation].op,
1730 &effect->current_light[state->index], param_value);
1731 effect->light_updated |= 1u << state->index;
1732 return D3D_OK;
1734 case SC_MATERIAL:
1736 TRACE("%s, index %u, op %u.\n", state_table[state->operation].name, state->index,
1737 state_table[state->operation].op);
1738 d3dx9_set_material_parameter(state_table[state->operation].op,
1739 &effect->current_material, param_value);
1740 effect->material_updated = TRUE;
1741 return D3D_OK;
1743 case SC_NPATCHMODE:
1744 TRACE("%s, nsegments %f.\n", state_table[state->operation].name, *(float *)param_value);
1745 return SET_D3D_STATE(effect, SetNPatchMode, *(float *)param_value);
1746 case SC_SHADERCONST:
1747 TRACE("%s, index %u, op %u.\n", state_table[state->operation].name, state->index,
1748 state_table[state->operation].op);
1749 return d3dx_set_shader_const_state(effect, state_table[state->operation].op, state->index,
1750 param, param_value);
1751 default:
1752 FIXME("%s not handled.\n", state_table[state->operation].name);
1753 break;
1755 return D3D_OK;
1758 static HRESULT d3dx9_apply_pass_states(struct d3dx_effect *effect, struct d3dx_pass *pass, BOOL update_all)
1760 unsigned int i;
1761 HRESULT ret;
1762 HRESULT hr;
1763 ULONG64 new_update_version = next_effect_update_version(effect);
1765 TRACE("effect %p, pass %p, state_count %u.\n", effect, pass, pass->state_count);
1767 ret = D3D_OK;
1768 for (i = 0; i < pass->state_count; ++i)
1770 if (FAILED(hr = d3dx9_apply_state(effect, pass, &pass->states[i], ~0u, update_all)))
1772 WARN("Error applying state, hr %#lx.\n", hr);
1773 ret = hr;
1777 if (effect->light_updated)
1779 for (i = 0; i < ARRAY_SIZE(effect->current_light); ++i)
1781 if ((effect->light_updated & (1u << i))
1782 && FAILED(hr = SET_D3D_STATE(effect, SetLight, i, &effect->current_light[i])))
1784 WARN("Error setting light, hr %#lx.\n", hr);
1785 ret = hr;
1788 effect->light_updated = 0;
1791 if (effect->material_updated
1792 && FAILED(hr = SET_D3D_STATE(effect, SetMaterial, &effect->current_material)))
1794 WARN("Error setting material, hr %#lx.\n", hr);
1795 ret = hr;
1797 effect->material_updated = FALSE;
1799 pass->update_version = new_update_version;
1800 return ret;
1803 static void param_set_data_pointer(struct d3dx_parameter *param, unsigned char *data, BOOL child, BOOL free_data)
1805 unsigned char *member_data = data;
1806 unsigned int i, count;
1808 count = param->element_count ? param->element_count : param->member_count;
1809 for (i = 0; i < count; ++i)
1811 param_set_data_pointer(&param->members[i], member_data, TRUE, free_data);
1812 if (data)
1813 member_data += param->members[i].bytes;
1815 if (free_data)
1816 free_parameter_data(param, child);
1817 param->data = data;
1820 static BOOL is_same_parameter(void *param1_, struct d3dx_parameter *param2)
1822 struct d3dx_parameter *param1 = (struct d3dx_parameter *)param1_;
1823 BOOL matches;
1824 unsigned int i, member_count;
1826 matches = !strcmp(param1->name, param2->name) && param1->class == param2->class
1827 && param1->type == param2->type && param1->rows == param2->rows
1828 && param1->columns == param2->columns && param1->element_count == param2->element_count
1829 && param1->member_count == param2->member_count;
1831 member_count = param1->element_count ? param1->element_count : param1->member_count;
1833 if (!matches || !member_count)
1834 return matches;
1836 for (i = 0; i < member_count; ++i)
1838 if (!is_same_parameter(&param1->members[i], &param2->members[i]))
1839 return FALSE;
1841 return TRUE;
1844 static HRESULT d3dx_pool_sync_shared_parameter(struct d3dx_effect_pool *pool, struct d3dx_top_level_parameter *param)
1846 unsigned int i, free_entry_index;
1847 unsigned int new_size, new_count;
1849 if (!(param->param.flags & PARAMETER_FLAG_SHARED) || !pool || is_param_type_sampler(param->param.type))
1850 return D3D_OK;
1852 free_entry_index = pool->size;
1853 for (i = 0; i < pool->size; ++i)
1855 if (!pool->shared_data[i].count)
1856 free_entry_index = i;
1857 else if (is_same_parameter(&param->param, &pool->shared_data[i].parameters[0]->param))
1858 break;
1860 if (i == pool->size)
1862 i = free_entry_index;
1863 if (i == pool->size)
1865 struct d3dx_shared_data *new_alloc;
1867 if (!pool->size)
1869 new_size = INITIAL_POOL_SIZE;
1870 new_alloc = calloc(new_size, sizeof(*pool->shared_data));
1871 if (!new_alloc)
1872 goto oom;
1874 else
1876 new_size = pool->size * 2;
1877 new_alloc = _recalloc(pool->shared_data, new_size, sizeof(*pool->shared_data));
1878 if (!new_alloc)
1879 goto oom;
1880 if (new_alloc != pool->shared_data)
1882 unsigned int j, k;
1884 for (j = 0; j < pool->size; ++j)
1885 for (k = 0; k < new_alloc[j].count; ++k)
1886 new_alloc[j].parameters[k]->shared_data = &new_alloc[j];
1889 pool->shared_data = new_alloc;
1890 pool->size = new_size;
1892 pool->shared_data[i].data = param->param.data;
1894 else
1896 param_set_data_pointer(&param->param, pool->shared_data[i].data, FALSE, TRUE);
1898 new_count = ++pool->shared_data[i].count;
1899 if (new_count >= pool->shared_data[i].size)
1901 struct d3dx_top_level_parameter **new_alloc;
1903 new_size = pool->shared_data[i].size ? pool->shared_data[i].size * 2 : INITIAL_SHARED_DATA_SIZE;
1904 new_alloc = _recalloc(pool->shared_data[i].parameters, new_size, sizeof(*pool->shared_data[i].parameters));
1905 if (!new_alloc)
1906 goto oom;
1907 pool->shared_data[i].parameters = new_alloc;
1908 pool->shared_data[i].size = new_size;
1911 param->shared_data = &pool->shared_data[i];
1912 pool->shared_data[i].parameters[new_count - 1] = param;
1914 TRACE("name %s, parameter idx %u, new refcount %u.\n", debugstr_a(param->param.name), i,
1915 new_count);
1917 return D3D_OK;
1919 oom:
1920 ERR("Out of memory.\n");
1921 return E_OUTOFMEMORY;
1924 static BOOL param_zero_data_func(void *dummy, struct d3dx_parameter *param)
1926 param->data = NULL;
1927 return FALSE;
1930 static void d3dx_pool_release_shared_parameter(struct d3dx_top_level_parameter *param)
1932 unsigned int new_count;
1934 if (!(param->param.flags & PARAMETER_FLAG_SHARED) || !param->shared_data)
1935 return;
1936 new_count = --param->shared_data->count;
1938 TRACE("param %p, param->shared_data %p, new_count %d.\n", param, param->shared_data, new_count);
1940 if (new_count)
1942 unsigned int i;
1944 for (i = 0; i < new_count; ++i)
1946 if (param->shared_data->parameters[i] == param)
1948 memmove(&param->shared_data->parameters[i],
1949 &param->shared_data->parameters[i + 1],
1950 sizeof(param->shared_data->parameters[i]) * (new_count - i));
1951 break;
1954 walk_parameter_tree(&param->param, param_zero_data_func, NULL);
1956 else
1958 free(param->shared_data->parameters);
1959 /* Zeroing table size is required as the entry in pool parameters table can be reused. */
1960 param->shared_data->size = 0;
1961 param->shared_data = NULL;
1965 static inline struct d3dx_effect_pool *impl_from_ID3DXEffectPool(ID3DXEffectPool *iface)
1967 return CONTAINING_RECORD(iface, struct d3dx_effect_pool, ID3DXEffectPool_iface);
1970 static inline struct d3dx_effect_pool *unsafe_impl_from_ID3DXEffectPool(ID3DXEffectPool *iface);
1972 static inline struct d3dx_effect *impl_from_ID3DXEffect(ID3DXEffect *iface)
1974 return CONTAINING_RECORD(iface, struct d3dx_effect, ID3DXEffect_iface);
1977 /*** IUnknown methods ***/
1978 static HRESULT WINAPI d3dx_effect_QueryInterface(ID3DXEffect *iface, REFIID riid, void **object)
1980 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), object);
1982 if (IsEqualGUID(riid, &IID_IUnknown) ||
1983 IsEqualGUID(riid, &IID_ID3DXEffect))
1985 iface->lpVtbl->AddRef(iface);
1986 *object = iface;
1987 return S_OK;
1990 ERR("Interface %s not found\n", debugstr_guid(riid));
1992 return E_NOINTERFACE;
1995 static ULONG WINAPI d3dx_effect_AddRef(ID3DXEffect *iface)
1997 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
1998 ULONG refcount = InterlockedIncrement(&effect->ref);
2000 TRACE("%p increasing refcount to %lu.\n", effect, refcount);
2002 return refcount;
2005 static ULONG WINAPI d3dx_effect_Release(ID3DXEffect *iface)
2007 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2008 ULONG refcount = InterlockedDecrement(&effect->ref);
2010 TRACE("%p decreasing refcount to %lu.\n", effect, refcount);
2012 if (!refcount)
2013 d3dx_effect_cleanup(effect);
2015 return refcount;
2018 /*** ID3DXBaseEffect methods ***/
2019 static HRESULT WINAPI d3dx_effect_GetDesc(ID3DXEffect *iface, D3DXEFFECT_DESC *desc)
2021 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2023 FIXME("iface %p, desc %p partial stub.\n", iface, desc);
2025 if (!desc)
2027 WARN("Invalid argument specified.\n");
2028 return D3DERR_INVALIDCALL;
2031 /* TODO: add creator and function count. */
2032 desc->Creator = NULL;
2033 desc->Functions = 0;
2034 desc->Parameters = effect->params.count;
2035 desc->Techniques = effect->technique_count;
2037 return D3D_OK;
2040 static HRESULT WINAPI d3dx_effect_GetParameterDesc(ID3DXEffect *iface, D3DXHANDLE parameter,
2041 D3DXPARAMETER_DESC *desc)
2043 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2044 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2046 TRACE("iface %p, parameter %p, desc %p.\n", iface, parameter, desc);
2048 if (!desc || !param)
2050 WARN("Invalid argument specified.\n");
2051 return D3DERR_INVALIDCALL;
2054 desc->Name = param->name;
2055 desc->Semantic = param->semantic;
2056 desc->Class = param->class;
2057 desc->Type = param->type;
2058 desc->Rows = param->rows;
2059 desc->Columns = param->columns;
2060 desc->Elements = param->element_count;
2061 desc->Annotations = is_top_level_parameter(param)
2062 ? top_level_parameter_from_parameter(param)->annotation_count : 0;
2063 desc->StructMembers = param->member_count;
2064 desc->Flags = param->flags;
2065 desc->Bytes = param->bytes;
2067 return D3D_OK;
2070 static HRESULT WINAPI d3dx_effect_GetTechniqueDesc(ID3DXEffect *iface, D3DXHANDLE technique,
2071 D3DXTECHNIQUE_DESC *desc)
2073 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2074 struct d3dx_technique *tech = technique ? get_valid_technique(effect, technique) : &effect->techniques[0];
2076 TRACE("iface %p, technique %p, desc %p.\n", iface, technique, desc);
2078 if (!desc || !tech)
2080 WARN("Invalid argument specified.\n");
2081 return D3DERR_INVALIDCALL;
2084 desc->Name = tech->name;
2085 desc->Passes = tech->pass_count;
2086 desc->Annotations = tech->annotation_count;
2088 return D3D_OK;
2091 static HRESULT WINAPI d3dx_effect_GetPassDesc(ID3DXEffect *iface, D3DXHANDLE pass_handle, D3DXPASS_DESC *desc)
2093 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2094 struct d3dx_pass *pass = get_valid_pass(effect, pass_handle);
2095 unsigned int i;
2097 TRACE("iface %p, pass %p, desc %p.\n", iface, pass, desc);
2099 if (!desc || !pass)
2101 WARN("Invalid argument specified.\n");
2102 return D3DERR_INVALIDCALL;
2105 desc->Name = pass->name;
2106 desc->Annotations = pass->annotation_count;
2108 desc->pVertexShaderFunction = NULL;
2109 desc->pPixelShaderFunction = NULL;
2111 if (effect->flags & D3DXFX_NOT_CLONEABLE)
2112 return D3D_OK;
2114 for (i = 0; i < pass->state_count; ++i)
2116 struct d3dx_state *state = &pass->states[i];
2118 if (state_table[state->operation].class == SC_VERTEXSHADER
2119 || state_table[state->operation].class == SC_PIXELSHADER)
2121 struct d3dx_parameter *param;
2122 void *param_value;
2123 BOOL param_dirty;
2124 HRESULT hr;
2125 void *data;
2127 if (FAILED(hr = d3dx9_get_param_value_ptr(pass, &pass->states[i], &param_value, &param,
2128 FALSE, &param_dirty)))
2129 return hr;
2131 data = param->object_id ? effect->objects[param->object_id].data : NULL;
2132 if (state_table[state->operation].class == SC_VERTEXSHADER)
2133 desc->pVertexShaderFunction = data;
2134 else
2135 desc->pPixelShaderFunction = data;
2139 return D3D_OK;
2142 static HRESULT WINAPI d3dx_effect_GetFunctionDesc(ID3DXEffect *iface, D3DXHANDLE shader,
2143 D3DXFUNCTION_DESC *desc)
2145 FIXME("iface %p, shader %p, desc %p stub.\n", iface, shader, desc);
2147 return E_NOTIMPL;
2150 static D3DXHANDLE WINAPI d3dx_effect_GetParameter(ID3DXEffect *iface, D3DXHANDLE parameter, UINT index)
2152 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2153 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2155 TRACE("iface %p, parameter %p, index %u.\n", iface, parameter, index);
2157 if (!parameter)
2159 if (index < effect->params.count)
2161 TRACE("Returning parameter %p.\n", &effect->params.parameters[index]);
2162 return get_parameter_handle(&effect->params.parameters[index].param);
2165 else
2167 if (param && !param->element_count && index < param->member_count)
2169 TRACE("Returning parameter %p.\n", &param->members[index]);
2170 return get_parameter_handle(&param->members[index]);
2174 WARN("Parameter not found.\n");
2176 return NULL;
2179 static D3DXHANDLE WINAPI d3dx_effect_GetParameterByName(ID3DXEffect *iface, D3DXHANDLE parameter,
2180 const char *name)
2182 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2183 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2184 D3DXHANDLE handle;
2186 TRACE("iface %p, parameter %p, name %s.\n", iface, parameter, debugstr_a(name));
2188 if (!name)
2190 handle = get_parameter_handle(param);
2191 TRACE("Returning parameter %p.\n", handle);
2192 return handle;
2195 handle = get_parameter_handle(get_parameter_by_name(&effect->params, param, name));
2196 TRACE("Returning parameter %p.\n", handle);
2198 return handle;
2201 static D3DXHANDLE WINAPI d3dx_effect_GetParameterBySemantic(ID3DXEffect *iface, D3DXHANDLE parameter,
2202 const char *semantic)
2204 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2205 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2206 struct d3dx_parameter *temp_param;
2207 unsigned int i;
2209 TRACE("iface %p, parameter %p, semantic %s.\n", iface, parameter, debugstr_a(semantic));
2211 if (!parameter)
2213 for (i = 0; i < effect->params.count; ++i)
2215 temp_param = &effect->params.parameters[i].param;
2217 if (!temp_param->semantic)
2219 if (!semantic)
2221 TRACE("Returning parameter %p\n", temp_param);
2222 return get_parameter_handle(temp_param);
2224 continue;
2227 if (!stricmp(temp_param->semantic, semantic))
2229 TRACE("Returning parameter %p\n", temp_param);
2230 return get_parameter_handle(temp_param);
2234 else if (param)
2236 for (i = 0; i < param->member_count; ++i)
2238 temp_param = &param->members[i];
2240 if (!temp_param->semantic)
2242 if (!semantic)
2244 TRACE("Returning parameter %p\n", temp_param);
2245 return get_parameter_handle(temp_param);
2247 continue;
2250 if (!stricmp(temp_param->semantic, semantic))
2252 TRACE("Returning parameter %p\n", temp_param);
2253 return get_parameter_handle(temp_param);
2258 WARN("Parameter not found.\n");
2260 return NULL;
2263 static D3DXHANDLE WINAPI d3dx_effect_GetParameterElement(ID3DXEffect *iface, D3DXHANDLE parameter, UINT index)
2265 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2266 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2268 TRACE("iface %p, parameter %p, index %u.\n", iface, parameter, index);
2270 if (!param)
2272 if (index < effect->params.count)
2274 TRACE("Returning parameter %p.\n", &effect->params.parameters[index]);
2275 return get_parameter_handle(&effect->params.parameters[index].param);
2278 else
2280 if (index < param->element_count)
2282 TRACE("Returning parameter %p.\n", &param->members[index]);
2283 return get_parameter_handle(&param->members[index]);
2287 WARN("Parameter not found.\n");
2289 return NULL;
2292 static D3DXHANDLE WINAPI d3dx_effect_GetTechnique(ID3DXEffect *iface, UINT index)
2294 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2296 TRACE("iface %p, index %u.\n", iface, index);
2298 if (index >= effect->technique_count)
2300 WARN("Invalid argument specified.\n");
2301 return NULL;
2304 TRACE("Returning technique %p.\n", &effect->techniques[index]);
2306 return get_technique_handle(&effect->techniques[index]);
2309 static D3DXHANDLE WINAPI d3dx_effect_GetTechniqueByName(ID3DXEffect *iface, const char *name)
2311 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2312 struct d3dx_technique *tech = get_technique_by_name(effect, name);
2314 TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
2316 if (tech)
2318 D3DXHANDLE t = get_technique_handle(tech);
2319 TRACE("Returning technique %p\n", t);
2320 return t;
2323 WARN("Technique not found.\n");
2325 return NULL;
2328 static D3DXHANDLE WINAPI d3dx_effect_GetPass(ID3DXEffect *iface, D3DXHANDLE technique, UINT index)
2330 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2331 struct d3dx_technique *tech = get_valid_technique(effect, technique);
2333 TRACE("iface %p, technique %p, index %u.\n", iface, technique, index);
2335 if (tech && index < tech->pass_count)
2337 TRACE("Returning pass %p\n", &tech->passes[index]);
2338 return get_pass_handle(&tech->passes[index]);
2341 WARN("Pass not found.\n");
2343 return NULL;
2346 static D3DXHANDLE WINAPI d3dx_effect_GetPassByName(ID3DXEffect *iface, D3DXHANDLE technique, const char *name)
2348 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2349 struct d3dx_technique *tech = get_valid_technique(effect, technique);
2351 TRACE("iface %p, technique %p, name %s.\n", iface, technique, debugstr_a(name));
2353 if (tech && name)
2355 unsigned int i;
2357 for (i = 0; i < tech->pass_count; ++i)
2359 struct d3dx_pass *pass = &tech->passes[i];
2361 if (!strcmp(pass->name, name))
2363 TRACE("Returning pass %p\n", pass);
2364 return get_pass_handle(pass);
2369 WARN("Pass not found.\n");
2371 return NULL;
2374 static D3DXHANDLE WINAPI d3dx_effect_GetFunction(ID3DXEffect *iface, UINT index)
2376 FIXME("iface %p, index %u stub.\n", iface, index);
2378 return NULL;
2381 static D3DXHANDLE WINAPI d3dx_effect_GetFunctionByName(ID3DXEffect *iface, const char *name)
2383 FIXME("iface %p, name %s stub.\n", iface, debugstr_a(name));
2385 return NULL;
2388 static D3DXHANDLE WINAPI d3dx_effect_GetAnnotation(ID3DXEffect *iface, D3DXHANDLE object, UINT index)
2390 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2391 struct d3dx_parameter *annotations = NULL;
2392 unsigned int annotation_count;
2394 TRACE("iface %p, object %p, index %u.\n", iface, object, index);
2396 annotation_count = get_annotation_from_object(effect, object, &annotations);
2398 if (index < annotation_count)
2400 TRACE("Returning parameter %p\n", &annotations[index]);
2401 return get_parameter_handle(&annotations[index]);
2404 WARN("Annotation not found.\n");
2406 return NULL;
2409 static D3DXHANDLE WINAPI d3dx_effect_GetAnnotationByName(ID3DXEffect *iface, D3DXHANDLE object,
2410 const char *name)
2412 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2413 struct d3dx_parameter *annotation = NULL;
2414 struct d3dx_parameter *annotations = NULL;
2415 unsigned int annotation_count;
2417 TRACE("iface %p, object %p, name %s.\n", iface, object, debugstr_a(name));
2419 if (!name)
2421 WARN("Invalid argument specified\n");
2422 return NULL;
2425 annotation_count = get_annotation_from_object(effect, object, &annotations);
2427 annotation = get_annotation_by_name(effect, annotation_count, annotations, name);
2428 if (annotation)
2430 TRACE("Returning parameter %p\n", annotation);
2431 return get_parameter_handle(annotation);
2434 WARN("Annotation not found.\n");
2436 return NULL;
2439 static HRESULT WINAPI d3dx_effect_SetValue(ID3DXEffect *iface, D3DXHANDLE parameter,
2440 const void *data, UINT bytes)
2442 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2443 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2445 TRACE("iface %p, parameter %p, data %p, bytes %u.\n", iface, parameter, data, bytes);
2447 if (!param)
2449 WARN("Invalid parameter %p specified.\n", parameter);
2450 return D3DERR_INVALIDCALL;
2452 if (param->class == D3DXPC_OBJECT && is_param_type_sampler(param->type))
2454 WARN("Parameter is a sampler, returning E_FAIL.\n");
2455 return E_FAIL;
2458 if (data && param->bytes <= bytes)
2459 return set_value(param, data, bytes, param_get_data_and_dirtify(effect, param, param->bytes, TRUE));
2461 WARN("Invalid argument specified.\n");
2463 return D3DERR_INVALIDCALL;
2466 static HRESULT WINAPI d3dx_effect_GetValue(ID3DXEffect *iface, D3DXHANDLE parameter, void *data, UINT bytes)
2468 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2469 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2471 TRACE("iface %p, parameter %p, data %p, bytes %u.\n", iface, parameter, data, bytes);
2473 if (!param)
2475 WARN("Invalid parameter %p specified.\n", parameter);
2476 return D3DERR_INVALIDCALL;
2478 if (param->class == D3DXPC_OBJECT && is_param_type_sampler(param->type))
2480 WARN("Parameter is a sampler, returning E_FAIL.\n");
2481 return E_FAIL;
2484 if (data && param->bytes <= bytes)
2486 TRACE("Type %s.\n", debug_d3dxparameter_type(param->type));
2488 switch (param->type)
2490 case D3DXPT_VOID:
2491 case D3DXPT_BOOL:
2492 case D3DXPT_INT:
2493 case D3DXPT_FLOAT:
2494 case D3DXPT_STRING:
2495 break;
2497 case D3DXPT_VERTEXSHADER:
2498 case D3DXPT_PIXELSHADER:
2499 case D3DXPT_TEXTURE:
2500 case D3DXPT_TEXTURE1D:
2501 case D3DXPT_TEXTURE2D:
2502 case D3DXPT_TEXTURE3D:
2503 case D3DXPT_TEXTURECUBE:
2505 unsigned int i;
2507 for (i = 0; i < (param->element_count ? param->element_count : 1); ++i)
2509 IUnknown *unk = ((IUnknown **)param->data)[i];
2510 if (unk)
2511 IUnknown_AddRef(unk);
2513 break;
2516 default:
2517 FIXME("Unhandled type %s.\n", debug_d3dxparameter_type(param->type));
2518 break;
2521 TRACE("Copy %u bytes.\n", param->bytes);
2522 memcpy(data, param->data, param->bytes);
2523 return D3D_OK;
2526 WARN("Parameter not found.\n");
2528 return D3DERR_INVALIDCALL;
2531 static HRESULT WINAPI d3dx_effect_SetBool(ID3DXEffect *iface, D3DXHANDLE parameter, BOOL b)
2533 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2534 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2536 TRACE("iface %p, parameter %p, b %#x.\n", iface, parameter, b);
2538 if (param && !param->element_count && param->rows == 1 && param->columns == 1)
2540 set_number(param_get_data_and_dirtify(effect, param, sizeof(int), TRUE),
2541 param->type, &b, D3DXPT_BOOL);
2542 return D3D_OK;
2545 WARN("Parameter not found.\n");
2547 return D3DERR_INVALIDCALL;
2550 static HRESULT WINAPI d3dx_effect_GetBool(ID3DXEffect *iface, D3DXHANDLE parameter, BOOL *b)
2552 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2553 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2555 TRACE("iface %p, parameter %p, b %p.\n", iface, parameter, b);
2557 if (b && param && !param->element_count && param->rows == 1 && param->columns == 1)
2559 set_number(b, D3DXPT_BOOL, param->data, param->type);
2560 TRACE("Returning %s\n", *b ? "TRUE" : "FALSE");
2561 return D3D_OK;
2564 WARN("Parameter not found.\n");
2566 return D3DERR_INVALIDCALL;
2569 static HRESULT WINAPI d3dx_effect_SetBoolArray(ID3DXEffect *iface, D3DXHANDLE parameter, const BOOL *b, UINT count)
2571 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2572 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2573 DWORD *data;
2575 TRACE("iface %p, parameter %p, b %p, count %u.\n", iface, parameter, b, count);
2577 if (param)
2579 unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2581 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2583 switch (param->class)
2585 case D3DXPC_SCALAR:
2586 case D3DXPC_VECTOR:
2587 case D3DXPC_MATRIX_ROWS:
2588 data = param_get_data_and_dirtify(effect, param, size * sizeof(int), TRUE);
2589 for (i = 0; i < size; ++i)
2591 /* don't crop the input, use D3DXPT_INT instead of D3DXPT_BOOL */
2592 set_number(data + i, param->type, &b[i], D3DXPT_INT);
2594 return D3D_OK;
2596 case D3DXPC_OBJECT:
2597 case D3DXPC_STRUCT:
2598 break;
2600 default:
2601 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2602 break;
2606 WARN("Parameter not found.\n");
2608 return D3DERR_INVALIDCALL;
2611 static HRESULT WINAPI d3dx_effect_GetBoolArray(ID3DXEffect *iface, D3DXHANDLE parameter, BOOL *b, UINT count)
2613 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2614 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2616 TRACE("iface %p, parameter %p, b %p, count %u.\n", iface, parameter, b, count);
2618 if (b && param && (param->class == D3DXPC_SCALAR
2619 || param->class == D3DXPC_VECTOR
2620 || param->class == D3DXPC_MATRIX_ROWS
2621 || param->class == D3DXPC_MATRIX_COLUMNS))
2623 unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2625 for (i = 0; i < size; ++i)
2627 set_number(&b[i], D3DXPT_BOOL, (DWORD *)param->data + i, param->type);
2629 return D3D_OK;
2632 WARN("Parameter not found.\n");
2634 return D3DERR_INVALIDCALL;
2637 static HRESULT WINAPI d3dx_effect_SetInt(ID3DXEffect *iface, D3DXHANDLE parameter, INT n)
2639 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2640 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2642 TRACE("iface %p, parameter %p, n %d.\n", iface, parameter, n);
2644 if (param && !param->element_count)
2646 if (param->rows == 1 && param->columns == 1)
2648 DWORD value;
2650 set_number(&value, param->type, &n, D3DXPT_INT);
2651 *(DWORD *)param_get_data_and_dirtify(effect, param, sizeof(int),
2652 value != *(DWORD *)param->data) = value;
2653 return D3D_OK;
2656 /* Split the value if parameter is a vector with dimension 3 or 4. */
2657 if (param->type == D3DXPT_FLOAT
2658 && ((param->class == D3DXPC_VECTOR && param->columns != 2)
2659 || (param->class == D3DXPC_MATRIX_ROWS && param->rows != 2 && param->columns == 1)))
2661 float *data;
2663 TRACE("Vector fixup.\n");
2665 data = param_get_data_and_dirtify(effect, param,
2666 min(4, param->rows * param->columns) * sizeof(float), TRUE);
2668 data[0] = ((n & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE;
2669 data[1] = ((n & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE;
2670 data[2] = (n & 0xff) * INT_FLOAT_MULTI_INVERSE;
2671 if (param->rows * param->columns > 3)
2672 data[3] = ((n & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE;
2674 return D3D_OK;
2678 WARN("Parameter not found.\n");
2680 return D3DERR_INVALIDCALL;
2683 static HRESULT WINAPI d3dx_effect_GetInt(ID3DXEffect *iface, D3DXHANDLE parameter, INT *n)
2685 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2686 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2688 TRACE("iface %p, parameter %p, n %p.\n", iface, parameter, n);
2690 if (n && param && !param->element_count)
2692 if (param->columns == 1 && param->rows == 1)
2694 set_number(n, D3DXPT_INT, param->data, param->type);
2695 TRACE("Returning %d.\n", *n);
2696 return D3D_OK;
2699 if (param->type == D3DXPT_FLOAT &&
2700 ((param->class == D3DXPC_VECTOR && param->columns != 2)
2701 || (param->class == D3DXPC_MATRIX_ROWS && param->rows != 2 && param->columns == 1)))
2703 TRACE("Vector fixup.\n");
2705 *n = min(max(0.0f, *((float *)param->data + 2)), 1.0f) * INT_FLOAT_MULTI;
2706 *n += ((int)(min(max(0.0f, *((float *)param->data + 1)), 1.0f) * INT_FLOAT_MULTI)) << 8;
2707 *n += ((int)(min(max(0.0f, *((float *)param->data + 0)), 1.0f) * INT_FLOAT_MULTI)) << 16;
2708 if (param->columns * param->rows > 3)
2709 *n += ((int)(min(max(0.0f, *((float *)param->data + 3)), 1.0f) * INT_FLOAT_MULTI)) << 24;
2711 TRACE("Returning %d.\n", *n);
2712 return D3D_OK;
2716 WARN("Parameter not found.\n");
2718 return D3DERR_INVALIDCALL;
2721 static HRESULT WINAPI d3dx_effect_SetIntArray(ID3DXEffect *iface, D3DXHANDLE parameter, const INT *n, UINT count)
2723 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2724 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2725 DWORD *data;
2727 TRACE("iface %p, parameter %p, n %p, count %u.\n", iface, parameter, n, count);
2729 if (param)
2731 unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2733 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2735 switch (param->class)
2737 case D3DXPC_SCALAR:
2738 case D3DXPC_VECTOR:
2739 case D3DXPC_MATRIX_ROWS:
2740 data = param_get_data_and_dirtify(effect, param, size * sizeof(int), TRUE);
2741 for (i = 0; i < size; ++i)
2742 set_number(data + i, param->type, &n[i], D3DXPT_INT);
2743 return D3D_OK;
2745 case D3DXPC_OBJECT:
2746 case D3DXPC_STRUCT:
2747 break;
2749 default:
2750 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2751 break;
2755 WARN("Parameter not found.\n");
2757 return D3DERR_INVALIDCALL;
2760 static HRESULT WINAPI d3dx_effect_GetIntArray(ID3DXEffect *iface, D3DXHANDLE parameter, INT *n, UINT count)
2762 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2763 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2765 TRACE("iface %p, parameter %p, n %p, count %u.\n", iface, parameter, n, count);
2767 if (n && param && (param->class == D3DXPC_SCALAR
2768 || param->class == D3DXPC_VECTOR
2769 || param->class == D3DXPC_MATRIX_ROWS
2770 || param->class == D3DXPC_MATRIX_COLUMNS))
2772 unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2774 for (i = 0; i < size; ++i)
2775 set_number(&n[i], D3DXPT_INT, (DWORD *)param->data + i, param->type);
2776 return D3D_OK;
2779 WARN("Parameter not found.\n");
2781 return D3DERR_INVALIDCALL;
2784 static HRESULT WINAPI d3dx_effect_SetFloat(ID3DXEffect *iface, D3DXHANDLE parameter, float f)
2786 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2787 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2789 TRACE("iface %p, parameter %p, f %.8e.\n", iface, parameter, f);
2791 if (param && !param->element_count && param->rows == 1 && param->columns == 1)
2793 DWORD value;
2795 set_number(&value, param->type, &f, D3DXPT_FLOAT);
2796 *(DWORD *)param_get_data_and_dirtify(effect, param, sizeof(float),
2797 value != *(DWORD *)param->data) = value;
2798 return D3D_OK;
2801 WARN("Parameter not found.\n");
2803 return D3DERR_INVALIDCALL;
2806 static HRESULT WINAPI d3dx_effect_GetFloat(ID3DXEffect *iface, D3DXHANDLE parameter, float *f)
2808 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2809 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2811 TRACE("iface %p, parameter %p, f %p.\n", iface, parameter, f);
2813 if (f && param && !param->element_count && param->columns == 1 && param->rows == 1)
2815 set_number(f, D3DXPT_FLOAT, (DWORD *)param->data, param->type);
2816 TRACE("Returning %f.\n", *f);
2817 return D3D_OK;
2820 WARN("Parameter not found.\n");
2822 return D3DERR_INVALIDCALL;
2825 static HRESULT WINAPI d3dx_effect_SetFloatArray(ID3DXEffect *iface, D3DXHANDLE parameter,
2826 const float *f, UINT count)
2828 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2829 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2830 DWORD *data;
2832 TRACE("iface %p, parameter %p, f %p, count %u.\n", iface, parameter, f, count);
2834 if (param)
2836 unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2838 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2840 switch (param->class)
2842 case D3DXPC_SCALAR:
2843 case D3DXPC_VECTOR:
2844 case D3DXPC_MATRIX_ROWS:
2845 data = param_get_data_and_dirtify(effect, param, size * sizeof(float), TRUE);
2846 for (i = 0; i < size; ++i)
2847 set_number(data + i, param->type, &f[i], D3DXPT_FLOAT);
2848 return D3D_OK;
2850 case D3DXPC_OBJECT:
2851 case D3DXPC_STRUCT:
2852 break;
2854 default:
2855 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2856 break;
2860 WARN("Parameter not found.\n");
2862 return D3DERR_INVALIDCALL;
2865 static HRESULT WINAPI d3dx_effect_GetFloatArray(ID3DXEffect *iface, D3DXHANDLE parameter, float *f, UINT count)
2867 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2868 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2870 TRACE("iface %p, parameter %p, f %p, count %u.\n", iface, parameter, f, count);
2872 if (f && param && (param->class == D3DXPC_SCALAR
2873 || param->class == D3DXPC_VECTOR
2874 || param->class == D3DXPC_MATRIX_ROWS
2875 || param->class == D3DXPC_MATRIX_COLUMNS))
2877 unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2879 for (i = 0; i < size; ++i)
2880 set_number(&f[i], D3DXPT_FLOAT, (DWORD *)param->data + i, param->type);
2881 return D3D_OK;
2884 WARN("Parameter not found.\n");
2886 return D3DERR_INVALIDCALL;
2889 static HRESULT WINAPI d3dx_effect_SetVector(ID3DXEffect *iface, D3DXHANDLE parameter, const D3DXVECTOR4 *vector)
2891 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2892 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2894 TRACE("iface %p, parameter %p, vector %p.\n", iface, parameter, vector);
2896 if (param && !param->element_count)
2898 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2900 switch (param->class)
2902 case D3DXPC_SCALAR:
2903 case D3DXPC_VECTOR:
2904 if (param->type == D3DXPT_INT && param->bytes == 4)
2906 DWORD tmp;
2908 TRACE("INT fixup.\n");
2909 tmp = max(min(vector->z, 1.0f), 0.0f) * INT_FLOAT_MULTI;
2910 tmp += ((DWORD)(max(min(vector->y, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 8;
2911 tmp += ((DWORD)(max(min(vector->x, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 16;
2912 tmp += ((DWORD)(max(min(vector->w, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 24;
2914 *(int *)param_get_data_and_dirtify(effect, param, sizeof(int), TRUE) = tmp;
2915 return D3D_OK;
2917 if (param->type == D3DXPT_FLOAT)
2919 memcpy(param_get_data_and_dirtify(effect, param, param->columns * sizeof(float), TRUE),
2920 vector, param->columns * sizeof(float));
2921 return D3D_OK;
2924 set_vector(param, vector, param_get_data_and_dirtify(effect, param, param->columns * sizeof(float), TRUE));
2925 return D3D_OK;
2927 case D3DXPC_MATRIX_ROWS:
2928 case D3DXPC_OBJECT:
2929 case D3DXPC_STRUCT:
2930 break;
2932 default:
2933 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2934 break;
2938 WARN("Parameter not found.\n");
2940 return D3DERR_INVALIDCALL;
2943 static HRESULT WINAPI d3dx_effect_GetVector(ID3DXEffect *iface, D3DXHANDLE parameter, D3DXVECTOR4 *vector)
2945 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2946 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2948 TRACE("iface %p, parameter %p, vector %p.\n", iface, parameter, vector);
2950 if (vector && param && !param->element_count)
2952 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2954 switch (param->class)
2956 case D3DXPC_SCALAR:
2957 case D3DXPC_VECTOR:
2958 if (param->type == D3DXPT_INT && param->bytes == 4)
2960 TRACE("INT fixup.\n");
2961 vector->x = (((*(int *)param->data) & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE;
2962 vector->y = (((*(int *)param->data) & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE;
2963 vector->z = ((*(int *)param->data) & 0xff) * INT_FLOAT_MULTI_INVERSE;
2964 vector->w = (((*(int *)param->data) & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE;
2965 return D3D_OK;
2967 get_vector(param, vector);
2968 return D3D_OK;
2970 case D3DXPC_MATRIX_ROWS:
2971 case D3DXPC_OBJECT:
2972 case D3DXPC_STRUCT:
2973 break;
2975 default:
2976 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2977 break;
2981 WARN("Parameter not found.\n");
2983 return D3DERR_INVALIDCALL;
2986 static HRESULT WINAPI d3dx_effect_SetVectorArray(ID3DXEffect *iface, D3DXHANDLE parameter,
2987 const D3DXVECTOR4 *vector, UINT count)
2989 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2990 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2992 TRACE("iface %p, parameter %p, vector %p, count %u.\n", iface, parameter, vector, count);
2994 if (param && param->element_count && param->element_count >= count)
2996 unsigned int i;
2997 BYTE *data;
2999 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3001 switch (param->class)
3003 case D3DXPC_VECTOR:
3004 data = param_get_data_and_dirtify(effect, param, count * param->columns * sizeof(float), TRUE);
3006 if (param->type == D3DXPT_FLOAT)
3008 if (param->columns == 4)
3010 memcpy(data, vector, count * 4 * sizeof(float));
3012 else
3014 for (i = 0; i < count; ++i)
3015 memcpy((float *)data + param->columns * i, vector + i,
3016 param->columns * sizeof(float));
3018 return D3D_OK;
3021 for (i = 0; i < count; ++i)
3022 set_vector(&param->members[i], &vector[i], data + i * param->columns * sizeof(float));
3024 return D3D_OK;
3026 case D3DXPC_SCALAR:
3027 case D3DXPC_MATRIX_ROWS:
3028 case D3DXPC_OBJECT:
3029 case D3DXPC_STRUCT:
3030 break;
3032 default:
3033 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3034 break;
3038 WARN("Parameter not found.\n");
3040 return D3DERR_INVALIDCALL;
3043 static HRESULT WINAPI d3dx_effect_GetVectorArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3044 D3DXVECTOR4 *vector, UINT count)
3046 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3047 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3049 TRACE("iface %p, parameter %p, vector %p, count %u.\n", iface, parameter, vector, count);
3051 if (!count)
3052 return D3D_OK;
3054 if (vector && param && count <= param->element_count)
3056 unsigned int i;
3058 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3060 switch (param->class)
3062 case D3DXPC_VECTOR:
3063 for (i = 0; i < count; ++i)
3064 get_vector(&param->members[i], &vector[i]);
3065 return D3D_OK;
3067 case D3DXPC_SCALAR:
3068 case D3DXPC_MATRIX_ROWS:
3069 case D3DXPC_OBJECT:
3070 case D3DXPC_STRUCT:
3071 break;
3073 default:
3074 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3075 break;
3079 WARN("Parameter not found.\n");
3081 return D3DERR_INVALIDCALL;
3084 static HRESULT WINAPI d3dx_effect_SetMatrix(ID3DXEffect *iface, D3DXHANDLE parameter, const D3DXMATRIX *matrix)
3086 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3087 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3089 TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3091 if (param && !param->element_count)
3093 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3095 switch (param->class)
3097 case D3DXPC_MATRIX_ROWS:
3098 set_matrix(param, matrix, param_get_data_and_dirtify(effect, param,
3099 param->rows * param->columns * sizeof(float), TRUE));
3100 return D3D_OK;
3102 case D3DXPC_SCALAR:
3103 case D3DXPC_VECTOR:
3104 case D3DXPC_OBJECT:
3105 case D3DXPC_STRUCT:
3106 break;
3108 default:
3109 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3110 break;
3114 WARN("Parameter not found.\n");
3116 return D3DERR_INVALIDCALL;
3119 static HRESULT WINAPI d3dx_effect_GetMatrix(ID3DXEffect *iface, D3DXHANDLE parameter, D3DXMATRIX *matrix)
3121 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3122 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3124 TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3126 if (matrix && param && !param->element_count)
3128 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3130 switch (param->class)
3132 case D3DXPC_MATRIX_ROWS:
3133 get_matrix(param, matrix, FALSE);
3134 return D3D_OK;
3136 case D3DXPC_SCALAR:
3137 case D3DXPC_VECTOR:
3138 case D3DXPC_OBJECT:
3139 case D3DXPC_STRUCT:
3140 break;
3142 default:
3143 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3144 break;
3148 WARN("Parameter not found.\n");
3150 return D3DERR_INVALIDCALL;
3153 static HRESULT WINAPI d3dx_effect_SetMatrixArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3154 const D3DXMATRIX *matrix, UINT count)
3156 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3157 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3159 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3161 if (param && param->element_count >= count)
3163 unsigned int i;
3164 BYTE *data;
3166 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3168 switch (param->class)
3170 case D3DXPC_MATRIX_ROWS:
3171 data = param_get_data_and_dirtify(effect, param, count * param->rows
3172 * param->columns * sizeof(float), TRUE);
3174 for (i = 0; i < count; ++i)
3175 set_matrix(&param->members[i], &matrix[i],
3176 data + i * param->rows * param->columns * sizeof(float));
3178 return D3D_OK;
3180 case D3DXPC_SCALAR:
3181 case D3DXPC_VECTOR:
3182 case D3DXPC_OBJECT:
3183 case D3DXPC_STRUCT:
3184 break;
3186 default:
3187 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3188 break;
3192 WARN("Parameter not found.\n");
3194 return D3DERR_INVALIDCALL;
3197 static HRESULT WINAPI d3dx_effect_GetMatrixArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3198 D3DXMATRIX *matrix, UINT count)
3200 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3201 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3203 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3205 if (!count)
3206 return D3D_OK;
3208 if (matrix && param && count <= param->element_count)
3210 unsigned int i;
3212 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3214 switch (param->class)
3216 case D3DXPC_MATRIX_ROWS:
3217 for (i = 0; i < count; ++i)
3218 get_matrix(&param->members[i], &matrix[i], FALSE);
3219 return D3D_OK;
3221 case D3DXPC_SCALAR:
3222 case D3DXPC_VECTOR:
3223 case D3DXPC_OBJECT:
3224 case D3DXPC_STRUCT:
3225 break;
3227 default:
3228 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3229 break;
3233 WARN("Parameter not found.\n");
3235 return D3DERR_INVALIDCALL;
3238 static HRESULT WINAPI d3dx_effect_SetMatrixPointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3239 const D3DXMATRIX **matrix, UINT count)
3241 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3242 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3244 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3246 if (param && count <= param->element_count)
3248 unsigned int i;
3249 BYTE *data;
3251 switch (param->class)
3253 case D3DXPC_MATRIX_ROWS:
3254 data = param_get_data_and_dirtify(effect, param, count * param->rows
3255 * param->columns * sizeof(float), TRUE);
3257 for (i = 0; i < count; ++i)
3258 set_matrix(&param->members[i], matrix[i], data + i * param->rows
3259 * param->columns * sizeof(float));
3261 return D3D_OK;
3263 case D3DXPC_SCALAR:
3264 case D3DXPC_VECTOR:
3265 case D3DXPC_OBJECT:
3266 break;
3268 default:
3269 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3270 break;
3274 WARN("Parameter not found.\n");
3276 return D3DERR_INVALIDCALL;
3279 static HRESULT WINAPI d3dx_effect_GetMatrixPointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3280 D3DXMATRIX **matrix, UINT count)
3282 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3283 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3285 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3287 if (!count)
3288 return D3D_OK;
3290 if (param && matrix && count <= param->element_count)
3292 unsigned int i;
3294 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3296 switch (param->class)
3298 case D3DXPC_MATRIX_ROWS:
3299 for (i = 0; i < count; ++i)
3300 get_matrix(&param->members[i], matrix[i], FALSE);
3301 return D3D_OK;
3303 case D3DXPC_SCALAR:
3304 case D3DXPC_VECTOR:
3305 case D3DXPC_OBJECT:
3306 break;
3308 default:
3309 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3310 break;
3314 WARN("Parameter not found.\n");
3316 return D3DERR_INVALIDCALL;
3319 static HRESULT WINAPI d3dx_effect_SetMatrixTranspose(ID3DXEffect *iface, D3DXHANDLE parameter,
3320 const D3DXMATRIX *matrix)
3322 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3323 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3325 TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3327 if (param && !param->element_count)
3329 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3331 switch (param->class)
3333 case D3DXPC_MATRIX_ROWS:
3334 set_matrix_transpose(param, matrix, param_get_data_and_dirtify(effect, param,
3335 param->rows * param->columns * sizeof(float), TRUE));
3336 return D3D_OK;
3338 case D3DXPC_SCALAR:
3339 case D3DXPC_VECTOR:
3340 case D3DXPC_OBJECT:
3341 case D3DXPC_STRUCT:
3342 break;
3344 default:
3345 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3346 break;
3350 WARN("Parameter not found.\n");
3352 return D3DERR_INVALIDCALL;
3355 static HRESULT WINAPI d3dx_effect_GetMatrixTranspose(ID3DXEffect *iface, D3DXHANDLE parameter,
3356 D3DXMATRIX *matrix)
3358 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3359 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3361 TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3363 if (matrix && param && !param->element_count)
3365 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3367 switch (param->class)
3369 case D3DXPC_SCALAR:
3370 case D3DXPC_VECTOR:
3371 get_matrix(param, matrix, FALSE);
3372 return D3D_OK;
3374 case D3DXPC_MATRIX_ROWS:
3375 get_matrix(param, matrix, TRUE);
3376 return D3D_OK;
3378 case D3DXPC_OBJECT:
3379 case D3DXPC_STRUCT:
3380 break;
3382 default:
3383 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3384 break;
3388 WARN("Parameter not found.\n");
3390 return D3DERR_INVALIDCALL;
3393 static HRESULT WINAPI d3dx_effect_SetMatrixTransposeArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3394 const D3DXMATRIX *matrix, UINT count)
3396 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3397 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3399 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3401 if (param && param->element_count >= count)
3403 unsigned int i;
3404 BYTE *data;
3406 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3408 switch (param->class)
3410 case D3DXPC_MATRIX_ROWS:
3411 data = param_get_data_and_dirtify(effect, param, count * param->rows
3412 * param->columns * sizeof(float), TRUE);
3414 for (i = 0; i < count; ++i)
3415 set_matrix_transpose(&param->members[i], &matrix[i], data
3416 + i * param->rows * param->columns * sizeof(float));
3418 return D3D_OK;
3420 case D3DXPC_SCALAR:
3421 case D3DXPC_VECTOR:
3422 case D3DXPC_OBJECT:
3423 case D3DXPC_STRUCT:
3424 break;
3426 default:
3427 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3428 break;
3432 WARN("Parameter not found.\n");
3434 return D3DERR_INVALIDCALL;
3437 static HRESULT WINAPI d3dx_effect_GetMatrixTransposeArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3438 D3DXMATRIX *matrix, UINT count)
3440 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3441 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3443 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3445 if (!count)
3446 return D3D_OK;
3448 if (matrix && param && count <= param->element_count)
3450 unsigned int i;
3452 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3454 switch (param->class)
3456 case D3DXPC_MATRIX_ROWS:
3457 for (i = 0; i < count; ++i)
3458 get_matrix(&param->members[i], &matrix[i], TRUE);
3459 return D3D_OK;
3461 case D3DXPC_SCALAR:
3462 case D3DXPC_VECTOR:
3463 case D3DXPC_OBJECT:
3464 case D3DXPC_STRUCT:
3465 break;
3467 default:
3468 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3469 break;
3473 WARN("Parameter not found.\n");
3475 return D3DERR_INVALIDCALL;
3478 static HRESULT WINAPI d3dx_effect_SetMatrixTransposePointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3479 const D3DXMATRIX **matrix, UINT count)
3481 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3482 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3484 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3486 if (param && count <= param->element_count)
3488 unsigned int i;
3489 BYTE *data;
3491 switch (param->class)
3493 case D3DXPC_MATRIX_ROWS:
3494 data = param_get_data_and_dirtify(effect, param, count * param->rows
3495 * param->columns * sizeof(float), TRUE);
3497 for (i = 0; i < count; ++i)
3498 set_matrix_transpose(&param->members[i], matrix[i], data
3499 + i * param->rows * param->columns * sizeof(float));
3501 return D3D_OK;
3503 case D3DXPC_SCALAR:
3504 case D3DXPC_VECTOR:
3505 case D3DXPC_OBJECT:
3506 break;
3508 default:
3509 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3510 break;
3514 WARN("Parameter not found.\n");
3516 return D3DERR_INVALIDCALL;
3519 static HRESULT WINAPI d3dx_effect_GetMatrixTransposePointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3520 D3DXMATRIX **matrix, UINT count)
3522 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3523 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3525 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3527 if (!count)
3528 return D3D_OK;
3530 if (matrix && param && count <= param->element_count)
3532 unsigned int i;
3534 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3536 switch (param->class)
3538 case D3DXPC_MATRIX_ROWS:
3539 for (i = 0; i < count; ++i)
3540 get_matrix(&param->members[i], matrix[i], TRUE);
3541 return D3D_OK;
3543 case D3DXPC_SCALAR:
3544 case D3DXPC_VECTOR:
3545 case D3DXPC_OBJECT:
3546 break;
3548 default:
3549 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3550 break;
3554 WARN("Parameter not found.\n");
3556 return D3DERR_INVALIDCALL;
3559 static HRESULT WINAPI d3dx_effect_SetString(ID3DXEffect *iface, D3DXHANDLE parameter, const char *string)
3561 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3562 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3564 TRACE("iface %p, parameter %p, string %s.\n", iface, parameter, debugstr_a(string));
3566 if (param && param->type == D3DXPT_STRING)
3567 return set_string(param_get_data_and_dirtify(effect, param, sizeof(void *), TRUE), string);
3569 WARN("Parameter not found.\n");
3571 return D3DERR_INVALIDCALL;
3574 static HRESULT WINAPI d3dx_effect_GetString(ID3DXEffect *iface, D3DXHANDLE parameter, const char **string)
3576 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3577 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3579 TRACE("iface %p, parameter %p, string %p.\n", iface, parameter, string);
3581 if (string && param && !param->element_count && param->type == D3DXPT_STRING)
3583 *string = *(const char **)param->data;
3584 TRACE("Returning %s.\n", debugstr_a(*string));
3585 return D3D_OK;
3588 WARN("Parameter not found.\n");
3590 return D3DERR_INVALIDCALL;
3593 static HRESULT WINAPI d3dx_effect_SetTexture(ID3DXEffect *iface, D3DXHANDLE parameter,
3594 IDirect3DBaseTexture9 *texture)
3596 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3597 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3599 TRACE("iface %p, parameter %p, texture %p.\n", iface, parameter, texture);
3601 if (param && !param->element_count
3602 && (param->type == D3DXPT_TEXTURE || param->type == D3DXPT_TEXTURE1D
3603 || param->type == D3DXPT_TEXTURE2D || param->type == D3DXPT_TEXTURE3D
3604 || param->type == D3DXPT_TEXTURECUBE))
3606 IDirect3DBaseTexture9 **data = param_get_data_and_dirtify(effect, param,
3607 sizeof(void *), texture != *(IDirect3DBaseTexture9 **)param->data);
3608 IDirect3DBaseTexture9 *old_texture = *data;
3610 *data = texture;
3612 if (texture == old_texture)
3613 return D3D_OK;
3615 if (texture)
3616 IDirect3DBaseTexture9_AddRef(texture);
3617 if (old_texture)
3618 IDirect3DBaseTexture9_Release(old_texture);
3620 return D3D_OK;
3623 WARN("Parameter not found.\n");
3625 return D3DERR_INVALIDCALL;
3628 static HRESULT WINAPI d3dx_effect_GetTexture(ID3DXEffect *iface, D3DXHANDLE parameter,
3629 IDirect3DBaseTexture9 **texture)
3631 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3632 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3634 TRACE("iface %p, parameter %p, texture %p.\n", iface, parameter, texture);
3636 if (texture && param && !param->element_count
3637 && (param->type == D3DXPT_TEXTURE || param->type == D3DXPT_TEXTURE1D
3638 || param->type == D3DXPT_TEXTURE2D || param->type == D3DXPT_TEXTURE3D
3639 || param->type == D3DXPT_TEXTURECUBE))
3641 *texture = *(IDirect3DBaseTexture9 **)param->data;
3642 if (*texture)
3643 IDirect3DBaseTexture9_AddRef(*texture);
3644 TRACE("Returning %p.\n", *texture);
3645 return D3D_OK;
3648 WARN("Parameter not found.\n");
3650 return D3DERR_INVALIDCALL;
3653 static HRESULT WINAPI d3dx_effect_GetPixelShader(ID3DXEffect *iface, D3DXHANDLE parameter,
3654 IDirect3DPixelShader9 **shader)
3656 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3657 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3659 TRACE("iface %p, parameter %p, shader %p.\n", iface, parameter, shader);
3661 if (shader && param && !param->element_count && param->type == D3DXPT_PIXELSHADER)
3663 if ((*shader = *(IDirect3DPixelShader9 **)param->data))
3664 IDirect3DPixelShader9_AddRef(*shader);
3665 TRACE("Returning %p.\n", *shader);
3666 return D3D_OK;
3669 WARN("Parameter not found.\n");
3671 return D3DERR_INVALIDCALL;
3674 static HRESULT WINAPI d3dx_effect_GetVertexShader(ID3DXEffect *iface, D3DXHANDLE parameter,
3675 IDirect3DVertexShader9 **shader)
3677 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3678 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3680 TRACE("iface %p, parameter %p, shader %p.\n", iface, parameter, shader);
3682 if (shader && param && !param->element_count && param->type == D3DXPT_VERTEXSHADER)
3684 if ((*shader = *(IDirect3DVertexShader9 **)param->data))
3685 IDirect3DVertexShader9_AddRef(*shader);
3686 TRACE("Returning %p.\n", *shader);
3687 return D3D_OK;
3690 WARN("Parameter not found.\n");
3692 return D3DERR_INVALIDCALL;
3695 static HRESULT WINAPI d3dx_effect_SetArrayRange(ID3DXEffect *iface, D3DXHANDLE parameter, UINT start, UINT end)
3697 FIXME("iface %p, parameter %p, start %u, end %u stub.\n", iface, parameter, start, end);
3699 return E_NOTIMPL;
3702 /*** ID3DXEffect methods ***/
3703 static HRESULT WINAPI d3dx_effect_GetPool(ID3DXEffect *iface, ID3DXEffectPool **pool)
3705 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3707 TRACE("iface %p, pool %p.\n", effect, pool);
3709 if (!pool)
3711 WARN("Invalid argument supplied.\n");
3712 return D3DERR_INVALIDCALL;
3715 *pool = NULL;
3716 if (effect->pool)
3718 *pool = &effect->pool->ID3DXEffectPool_iface;
3719 (*pool)->lpVtbl->AddRef(*pool);
3722 TRACE("Returning pool %p.\n", *pool);
3724 return S_OK;
3727 static HRESULT WINAPI d3dx_effect_SetTechnique(ID3DXEffect *iface, D3DXHANDLE technique)
3729 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3730 struct d3dx_technique *tech = get_valid_technique(effect, technique);
3732 TRACE("iface %p, technique %p\n", iface, technique);
3734 if (tech)
3736 effect->active_technique = tech;
3737 TRACE("Technique %p\n", tech);
3738 return D3D_OK;
3741 WARN("Technique not found.\n");
3743 return D3DERR_INVALIDCALL;
3746 static D3DXHANDLE WINAPI d3dx_effect_GetCurrentTechnique(ID3DXEffect *iface)
3748 struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
3750 TRACE("iface %p\n", This);
3752 return get_technique_handle(This->active_technique);
3755 static HRESULT WINAPI d3dx_effect_ValidateTechnique(ID3DXEffect *iface, D3DXHANDLE technique)
3757 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3758 struct d3dx_technique *tech = get_valid_technique(effect, technique);
3759 HRESULT ret = D3D_OK;
3760 unsigned int i, j;
3762 FIXME("iface %p, technique %p semi-stub.\n", iface, technique);
3764 if (!tech)
3766 ret = D3DERR_INVALIDCALL;
3767 goto done;
3769 for (i = 0; i < tech->pass_count; ++i)
3771 struct d3dx_pass *pass = &tech->passes[i];
3773 for (j = 0; j < pass->state_count; ++j)
3775 struct d3dx_state *state = &pass->states[j];
3777 if (state_table[state->operation].class == SC_VERTEXSHADER
3778 || state_table[state->operation].class == SC_PIXELSHADER)
3780 struct d3dx_parameter *param;
3781 void *param_value;
3782 BOOL param_dirty;
3783 HRESULT hr;
3785 if (FAILED(hr = d3dx9_get_param_value_ptr(pass, &pass->states[j], &param_value, &param,
3786 FALSE, &param_dirty)))
3787 return hr;
3789 if (param->object_id && effect->objects[param->object_id].creation_failed)
3791 ret = E_FAIL;
3792 goto done;
3797 done:
3798 TRACE("Returning %#lx.\n", ret);
3799 return ret;
3802 static HRESULT WINAPI d3dx_effect_FindNextValidTechnique(ID3DXEffect *iface, D3DXHANDLE technique,
3803 D3DXHANDLE *next_technique)
3805 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3806 struct d3dx_technique *prev_tech, *tech;
3807 unsigned int i;
3809 TRACE("iface %p, technique %p, next_technique %p.\n", iface, technique, next_technique);
3811 if (technique)
3813 if (!(prev_tech = get_valid_technique(effect, technique)))
3814 return D3DERR_INVALIDCALL;
3816 for (i = 0; i < effect->technique_count; ++i)
3818 tech = &effect->techniques[i];
3819 if (tech == prev_tech)
3821 ++i;
3822 break;
3826 else
3828 i = 0;
3831 for (; i < effect->technique_count; ++i)
3833 tech = &effect->techniques[i];
3834 if (SUCCEEDED(d3dx_effect_ValidateTechnique(iface, get_technique_handle(tech))))
3836 *next_technique = get_technique_handle(tech);
3837 return D3D_OK;
3841 *next_technique = NULL;
3842 return S_FALSE;
3845 static BOOL walk_parameter_dep(struct d3dx_parameter *param, walk_parameter_dep_func param_func,
3846 void *data);
3848 static BOOL walk_param_eval_dep(struct d3dx_param_eval *param_eval, walk_parameter_dep_func param_func,
3849 void *data)
3851 struct d3dx_parameter **params;
3852 unsigned int i, param_count;
3854 if (!param_eval)
3855 return FALSE;
3857 params = param_eval->shader_inputs.inputs_param;
3858 param_count = param_eval->shader_inputs.input_count;
3859 for (i = 0; i < param_count; ++i)
3861 if (walk_parameter_dep(params[i], param_func, data))
3862 return TRUE;
3865 params = param_eval->pres.inputs.inputs_param;
3866 param_count = param_eval->pres.inputs.input_count;
3867 for (i = 0; i < param_count; ++i)
3869 if (walk_parameter_dep(params[i], param_func, data))
3870 return TRUE;
3872 return FALSE;
3875 static BOOL walk_state_dep(struct d3dx_state *state, walk_parameter_dep_func param_func,
3876 void *data)
3878 if (state->type == ST_CONSTANT && is_param_type_sampler(state->parameter.type))
3880 if (walk_parameter_dep(&state->parameter, param_func, data))
3881 return TRUE;
3883 else if (state->type == ST_ARRAY_SELECTOR || state->type == ST_PARAMETER)
3885 if (walk_parameter_dep(state->referenced_param, param_func, data))
3886 return TRUE;
3888 return walk_param_eval_dep(state->parameter.param_eval, param_func, data);
3891 static BOOL walk_parameter_dep(struct d3dx_parameter *param, walk_parameter_dep_func param_func,
3892 void *data)
3894 unsigned int i;
3895 unsigned int member_count;
3897 param = &param->top_level_param->param;
3898 if (param_func(data, param))
3899 return TRUE;
3901 if (walk_param_eval_dep(param->param_eval, param_func, data))
3902 return TRUE;
3904 if (param->class == D3DXPC_OBJECT && is_param_type_sampler(param->type))
3906 struct d3dx_sampler *sampler;
3907 unsigned int sampler_idx;
3908 unsigned int samplers_count = max(param->element_count, 1);
3910 for (sampler_idx = 0; sampler_idx < samplers_count; ++sampler_idx)
3912 sampler = param->element_count ? param->members[sampler_idx].data : param->data;
3913 for (i = 0; i < sampler->state_count; ++i)
3915 if (walk_state_dep(&sampler->states[i], param_func, data))
3916 return TRUE;
3919 return FALSE;
3922 member_count = param->element_count ? param->element_count : param->member_count;
3923 for (i = 0; i < member_count; ++i)
3925 if (walk_param_eval_dep(param->members[i].param_eval, param_func, data))
3926 return TRUE;
3929 return FALSE;
3932 static BOOL is_parameter_used(struct d3dx_parameter *param, struct d3dx_technique *tech)
3934 unsigned int i, j;
3935 struct d3dx_pass *pass;
3937 if (!tech || !param)
3938 return FALSE;
3940 for (i = 0; i < tech->pass_count; ++i)
3942 pass = &tech->passes[i];
3943 for (j = 0; j < pass->state_count; ++j)
3945 if (walk_state_dep(&pass->states[j], is_same_parameter, param))
3946 return TRUE;
3949 return FALSE;
3952 static BOOL WINAPI d3dx_effect_IsParameterUsed(ID3DXEffect *iface, D3DXHANDLE parameter, D3DXHANDLE technique)
3954 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3955 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3956 struct d3dx_technique *tech = get_valid_technique(effect, technique);
3957 BOOL ret;
3959 TRACE("iface %p, parameter %p, technique %p.\n", iface, parameter, technique);
3960 TRACE("param %p, name %s, tech %p.\n", param, param ? debugstr_a(param->name) : "", tech);
3962 ret = is_parameter_used(param, tech);
3963 TRACE("Returning %#x.\n", ret);
3964 return ret;
3967 static HRESULT WINAPI d3dx_effect_Begin(ID3DXEffect *iface, UINT *passes, DWORD flags)
3969 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3970 struct d3dx_technique *technique = effect->active_technique;
3972 TRACE("iface %p, passes %p, flags %#lx.\n", iface, passes, flags);
3974 if (technique)
3976 if (flags & ~(D3DXFX_DONOTSAVESTATE | D3DXFX_DONOTSAVESAMPLERSTATE | D3DXFX_DONOTSAVESHADERSTATE))
3977 WARN("Invalid flags %#lx specified.\n", flags);
3979 if (flags & D3DXFX_DONOTSAVESTATE)
3981 TRACE("State capturing disabled.\n");
3983 else
3985 HRESULT hr;
3986 unsigned int i;
3988 if (!technique->saved_state)
3990 ID3DXEffectStateManager *manager;
3992 manager = effect->manager;
3993 effect->manager = NULL;
3994 if (FAILED(hr = IDirect3DDevice9_BeginStateBlock(effect->device)))
3995 ERR("BeginStateBlock failed, hr %#lx.\n", hr);
3996 for (i = 0; i < technique->pass_count; i++)
3997 d3dx9_apply_pass_states(effect, &technique->passes[i], TRUE);
3998 if (FAILED(hr = IDirect3DDevice9_EndStateBlock(effect->device, &technique->saved_state)))
3999 ERR("EndStateBlock failed, hr %#lx.\n", hr);
4000 effect->manager = manager;
4002 if (FAILED(hr = IDirect3DStateBlock9_Capture(technique->saved_state)))
4003 ERR("StateBlock Capture failed, hr %#lx.\n", hr);
4006 if (passes)
4007 *passes = technique->pass_count;
4008 effect->started = TRUE;
4009 effect->begin_flags = flags;
4011 return D3D_OK;
4014 WARN("Invalid argument supplied.\n");
4016 return D3DERR_INVALIDCALL;
4019 static HRESULT WINAPI d3dx_effect_BeginPass(ID3DXEffect *iface, UINT pass)
4021 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4022 struct d3dx_technique *technique = effect->active_technique;
4024 TRACE("iface %p, pass %u\n", effect, pass);
4026 if (!effect->started)
4028 WARN("Effect is not started, returning D3DERR_INVALIDCALL.\n");
4029 return D3DERR_INVALIDCALL;
4032 if (technique && pass < technique->pass_count && !effect->active_pass)
4034 HRESULT hr;
4036 memset(effect->current_light, 0, sizeof(effect->current_light));
4037 memset(&effect->current_material, 0, sizeof(effect->current_material));
4039 if (SUCCEEDED(hr = d3dx9_apply_pass_states(effect, &technique->passes[pass], TRUE)))
4040 effect->active_pass = &technique->passes[pass];
4041 return hr;
4044 WARN("Invalid argument supplied.\n");
4046 return D3DERR_INVALIDCALL;
4049 static HRESULT WINAPI d3dx_effect_CommitChanges(ID3DXEffect *iface)
4051 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4053 TRACE("iface %p.\n", iface);
4055 if (!effect->active_pass)
4057 WARN("Called without an active pass.\n");
4058 return D3D_OK;
4060 return d3dx9_apply_pass_states(effect, effect->active_pass, FALSE);
4063 static HRESULT WINAPI d3dx_effect_EndPass(ID3DXEffect *iface)
4065 struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4067 TRACE("iface %p\n", This);
4069 if (This->active_pass)
4071 This->active_pass = NULL;
4072 return D3D_OK;
4075 WARN("Invalid call.\n");
4077 return D3DERR_INVALIDCALL;
4080 static HRESULT WINAPI d3dx_effect_End(ID3DXEffect *iface)
4082 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4083 struct d3dx_technique *technique = effect->active_technique;
4085 TRACE("iface %p.\n", iface);
4087 if (!effect->started)
4088 return D3D_OK;
4090 if (effect->begin_flags & D3DXFX_DONOTSAVESTATE)
4092 TRACE("State restoring disabled.\n");
4094 else
4096 HRESULT hr;
4098 if (technique && technique->saved_state)
4100 if (FAILED(hr = IDirect3DStateBlock9_Apply(technique->saved_state)))
4101 ERR("State block apply failed, hr %#lx.\n", hr);
4103 else
4104 ERR("No saved state.\n");
4107 effect->started = FALSE;
4109 return D3D_OK;
4112 static HRESULT WINAPI d3dx_effect_GetDevice(ID3DXEffect *iface, struct IDirect3DDevice9 **device)
4114 struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4116 TRACE("iface %p, device %p\n", This, device);
4118 if (!device)
4120 WARN("Invalid argument supplied.\n");
4121 return D3DERR_INVALIDCALL;
4124 IDirect3DDevice9_AddRef(This->device);
4126 *device = This->device;
4128 TRACE("Returning device %p\n", *device);
4130 return S_OK;
4133 static BOOL param_on_lost_device(void *data, struct d3dx_parameter *param)
4135 struct IDirect3DVolumeTexture9 *volume_texture;
4136 struct IDirect3DCubeTexture9 *cube_texture;
4137 struct IDirect3DTexture9 *texture;
4138 D3DSURFACE_DESC surface_desc;
4139 D3DVOLUME_DESC volume_desc;
4141 if (param->class == D3DXPC_OBJECT && !param->element_count)
4143 switch (param->type)
4145 case D3DXPT_TEXTURE:
4146 case D3DXPT_TEXTURE1D:
4147 case D3DXPT_TEXTURE2D:
4148 texture = *(IDirect3DTexture9 **)param->data;
4149 if (!texture)
4150 return FALSE;
4151 IDirect3DTexture9_GetLevelDesc(texture, 0, &surface_desc);
4152 if (surface_desc.Pool != D3DPOOL_DEFAULT)
4153 return FALSE;
4154 break;
4155 case D3DXPT_TEXTURE3D:
4156 volume_texture = *(IDirect3DVolumeTexture9 **)param->data;
4157 if (!volume_texture)
4158 return FALSE;
4159 IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
4160 if (volume_desc.Pool != D3DPOOL_DEFAULT)
4161 return FALSE;
4162 break;
4163 case D3DXPT_TEXTURECUBE:
4164 cube_texture = *(IDirect3DCubeTexture9 **)param->data;
4165 if (!cube_texture)
4166 return FALSE;
4167 IDirect3DTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
4168 if (surface_desc.Pool != D3DPOOL_DEFAULT)
4169 return FALSE;
4170 break;
4171 default:
4172 return FALSE;
4174 IUnknown_Release(*(IUnknown **)param->data);
4175 *(IUnknown **)param->data = NULL;
4177 return FALSE;
4180 static HRESULT WINAPI d3dx_effect_OnLostDevice(ID3DXEffect *iface)
4182 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4183 unsigned int i;
4185 TRACE("iface %p.\n", iface);
4187 for (i = 0; i < effect->params.count; ++i)
4188 walk_parameter_tree(&effect->params.parameters[i].param, param_on_lost_device, NULL);
4190 return D3D_OK;
4193 static HRESULT WINAPI d3dx_effect_OnResetDevice(ID3DXEffect *iface)
4195 struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4197 FIXME("(%p)->(): stub\n", This);
4199 return E_NOTIMPL;
4202 static HRESULT WINAPI d3dx_effect_SetStateManager(ID3DXEffect *iface, ID3DXEffectStateManager *manager)
4204 struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4206 TRACE("iface %p, manager %p\n", This, manager);
4208 if (manager) IUnknown_AddRef(manager);
4209 if (This->manager) IUnknown_Release(This->manager);
4211 This->manager = manager;
4213 return D3D_OK;
4216 static HRESULT WINAPI d3dx_effect_GetStateManager(ID3DXEffect *iface, ID3DXEffectStateManager **manager)
4218 struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4220 TRACE("iface %p, manager %p\n", This, manager);
4222 if (!manager)
4224 WARN("Invalid argument supplied.\n");
4225 return D3DERR_INVALIDCALL;
4228 if (This->manager) IUnknown_AddRef(This->manager);
4229 *manager = This->manager;
4231 return D3D_OK;
4234 static HRESULT WINAPI d3dx_effect_BeginParameterBlock(ID3DXEffect *iface)
4236 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4238 TRACE("iface %p.\n", iface);
4240 if (effect->current_parameter_block)
4242 WARN("Parameter block is already started.\n");
4243 return D3DERR_INVALIDCALL;
4246 effect->current_parameter_block = calloc(1, sizeof(*effect->current_parameter_block));
4247 memcpy(effect->current_parameter_block->magic_string, parameter_block_magic_string,
4248 sizeof(parameter_block_magic_string));
4249 effect->current_parameter_block->effect = effect;
4251 return D3D_OK;
4254 static D3DXHANDLE WINAPI d3dx_effect_EndParameterBlock(ID3DXEffect *iface)
4256 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4257 struct d3dx_parameter_block *ret;
4258 BYTE *new_buffer;
4260 TRACE("iface %p.\n", iface);
4262 if (!effect->current_parameter_block)
4264 WARN("No active parameter block.\n");
4265 return NULL;
4267 ret = effect->current_parameter_block;
4269 new_buffer = realloc(ret->buffer, ret->offset);
4270 if (new_buffer)
4271 ret->buffer = new_buffer;
4272 ret->size = ret->offset;
4274 effect->current_parameter_block = NULL;
4275 list_add_tail(&effect->parameter_block_list, &ret->entry);
4276 return (D3DXHANDLE)ret;
4279 static HRESULT WINAPI d3dx_effect_ApplyParameterBlock(ID3DXEffect *iface, D3DXHANDLE parameter_block)
4281 struct d3dx_parameter_block *block = get_valid_parameter_block(parameter_block);
4282 struct d3dx_recorded_parameter *record;
4284 TRACE("iface %p, parameter_block %p.\n", iface, parameter_block);
4286 if (!block || !block->offset)
4287 return D3DERR_INVALIDCALL;
4289 record = (struct d3dx_recorded_parameter *)block->buffer;
4290 while ((BYTE *)record < block->buffer + block->offset)
4292 set_value(record->param, record + 1, record->bytes,
4293 param_get_data_and_dirtify(block->effect, record->param, record->bytes, TRUE));
4294 record = (struct d3dx_recorded_parameter *)((BYTE *)record + get_recorded_parameter_size(record));
4296 assert((BYTE *)record == block->buffer + block->offset);
4297 return D3D_OK;
4300 #if D3DX_SDK_VERSION >= 26
4301 static HRESULT WINAPI d3dx_effect_DeleteParameterBlock(ID3DXEffect *iface, D3DXHANDLE parameter_block)
4303 struct d3dx_parameter_block *block = get_valid_parameter_block(parameter_block);
4304 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4305 struct d3dx_parameter_block *b;
4307 TRACE("iface %p, parameter_block %p.\n", iface, parameter_block);
4309 if (!block)
4310 return D3DERR_INVALIDCALL;
4312 LIST_FOR_EACH_ENTRY(b, &effect->parameter_block_list, struct d3dx_parameter_block, entry)
4314 if (b == block)
4316 list_remove(&b->entry);
4317 free_parameter_block(b);
4318 return D3D_OK;
4322 WARN("Block is not found in issued block list, not freeing memory.\n");
4323 return D3DERR_INVALIDCALL;
4325 #endif
4327 static bool copy_parameter(struct d3dx_effect *dst_effect, const struct d3dx_effect *src_effect,
4328 struct d3dx_parameter *dst, const struct d3dx_parameter *src)
4330 IUnknown *iface;
4332 if ((src->flags & PARAMETER_FLAG_SHARED) && dst_effect->pool)
4333 return true;
4335 switch (src->type)
4337 case D3DXPT_VOID:
4338 case D3DXPT_BOOL:
4339 case D3DXPT_INT:
4340 case D3DXPT_FLOAT:
4341 memcpy(dst->data, src->data, src->bytes);
4342 break;
4344 case D3DXPT_STRING:
4345 free(*(char **)dst->data);
4346 if (!(*(char **)dst->data = strdup(*(char **)src->data)))
4347 return false;
4348 break;
4350 case D3DXPT_TEXTURE:
4351 case D3DXPT_TEXTURE1D:
4352 case D3DXPT_TEXTURE2D:
4353 case D3DXPT_TEXTURE3D:
4354 case D3DXPT_TEXTURECUBE:
4355 case D3DXPT_PIXELSHADER:
4356 case D3DXPT_VERTEXSHADER:
4357 iface = *(IUnknown **)src->data;
4358 if (src_effect->device == dst_effect->device && iface)
4360 if (*(IUnknown **)dst->data)
4361 IUnknown_Release(*(IUnknown **)dst->data);
4362 IUnknown_AddRef(iface);
4363 *(IUnknown **)dst->data = iface;
4365 break;
4367 case D3DXPT_SAMPLER:
4368 case D3DXPT_SAMPLER1D:
4369 case D3DXPT_SAMPLER2D:
4370 case D3DXPT_SAMPLER3D:
4371 case D3DXPT_SAMPLERCUBE:
4372 /* Nothing to do; these parameters are not mutable and cannot be
4373 * retrieved using API calls. */
4374 break;
4376 default:
4377 FIXME("Unhandled parameter type %#x.\n", src->type);
4380 return true;
4383 static HRESULT WINAPI d3dx_effect_CloneEffect(ID3DXEffect *iface, IDirect3DDevice9 *device, ID3DXEffect **out)
4385 struct d3dx_effect *src = impl_from_ID3DXEffect(iface);
4386 struct d3dx_effect *dst;
4387 unsigned int i, j, k;
4388 HRESULT hr;
4390 TRACE("iface %p, device %p, out %p.\n", iface, device, out);
4392 if (!out)
4393 return D3DERR_INVALIDCALL;
4395 if (src->flags & D3DXFX_NOT_CLONEABLE)
4396 return E_FAIL;
4398 if (!device)
4399 return D3DERR_INVALIDCALL;
4401 if (!(dst = calloc(1, sizeof(*dst))))
4402 return E_OUTOFMEMORY;
4404 if (FAILED(hr = d3dx9_effect_init_from_binary(dst, device, src->source, src->source_size,
4405 src->flags, &src->pool->ID3DXEffectPool_iface, src->skip_constants_string)))
4407 free(dst);
4408 return hr;
4411 for (i = 0; i < src->params.count; ++i)
4413 const struct d3dx_top_level_parameter *src_param = &src->params.parameters[i];
4414 struct d3dx_top_level_parameter *dst_param = &dst->params.parameters[i];
4416 copy_parameter(dst, src, &dst_param->param, &src_param->param);
4417 for (j = 0; j < src_param->annotation_count; ++j)
4418 copy_parameter(dst, src, &dst_param->annotations[j], &src_param->annotations[j]);
4421 for (i = 0; i < src->technique_count; ++i)
4423 const struct d3dx_technique *src_technique = &src->techniques[i];
4424 struct d3dx_technique *dst_technique = &dst->techniques[i];
4426 for (j = 0; j < src_technique->annotation_count; ++j)
4427 copy_parameter(dst, src, &dst_technique->annotations[j], &src_technique->annotations[j]);
4429 for (j = 0; j < src_technique->pass_count; ++j)
4431 const struct d3dx_pass *src_pass = &src_technique->passes[j];
4432 struct d3dx_pass *dst_pass = &dst_technique->passes[j];
4434 for (k = 0; k < src_pass->annotation_count; ++k)
4435 copy_parameter(dst, src, &dst_pass->annotations[k], &src_pass->annotations[k]);
4439 *out = &dst->ID3DXEffect_iface;
4440 TRACE("Created effect %p.\n", dst);
4441 return D3D_OK;
4444 #if D3DX_SDK_VERSION >= 27
4445 static HRESULT WINAPI d3dx_effect_SetRawValue(ID3DXEffect *iface, D3DXHANDLE parameter, const void *data,
4446 UINT byte_offset, UINT bytes)
4448 FIXME("iface %p, parameter %p, data %p, byte_offset %u, bytes %u stub!\n",
4449 iface, parameter, data, byte_offset, bytes);
4451 return E_NOTIMPL;
4453 #endif
4455 static const struct ID3DXEffectVtbl ID3DXEffect_Vtbl =
4457 /*** IUnknown methods ***/
4458 d3dx_effect_QueryInterface,
4459 d3dx_effect_AddRef,
4460 d3dx_effect_Release,
4461 /*** ID3DXBaseEffect methods ***/
4462 d3dx_effect_GetDesc,
4463 d3dx_effect_GetParameterDesc,
4464 d3dx_effect_GetTechniqueDesc,
4465 d3dx_effect_GetPassDesc,
4466 d3dx_effect_GetFunctionDesc,
4467 d3dx_effect_GetParameter,
4468 d3dx_effect_GetParameterByName,
4469 d3dx_effect_GetParameterBySemantic,
4470 d3dx_effect_GetParameterElement,
4471 d3dx_effect_GetTechnique,
4472 d3dx_effect_GetTechniqueByName,
4473 d3dx_effect_GetPass,
4474 d3dx_effect_GetPassByName,
4475 d3dx_effect_GetFunction,
4476 d3dx_effect_GetFunctionByName,
4477 d3dx_effect_GetAnnotation,
4478 d3dx_effect_GetAnnotationByName,
4479 d3dx_effect_SetValue,
4480 d3dx_effect_GetValue,
4481 d3dx_effect_SetBool,
4482 d3dx_effect_GetBool,
4483 d3dx_effect_SetBoolArray,
4484 d3dx_effect_GetBoolArray,
4485 d3dx_effect_SetInt,
4486 d3dx_effect_GetInt,
4487 d3dx_effect_SetIntArray,
4488 d3dx_effect_GetIntArray,
4489 d3dx_effect_SetFloat,
4490 d3dx_effect_GetFloat,
4491 d3dx_effect_SetFloatArray,
4492 d3dx_effect_GetFloatArray,
4493 d3dx_effect_SetVector,
4494 d3dx_effect_GetVector,
4495 d3dx_effect_SetVectorArray,
4496 d3dx_effect_GetVectorArray,
4497 d3dx_effect_SetMatrix,
4498 d3dx_effect_GetMatrix,
4499 d3dx_effect_SetMatrixArray,
4500 d3dx_effect_GetMatrixArray,
4501 d3dx_effect_SetMatrixPointerArray,
4502 d3dx_effect_GetMatrixPointerArray,
4503 d3dx_effect_SetMatrixTranspose,
4504 d3dx_effect_GetMatrixTranspose,
4505 d3dx_effect_SetMatrixTransposeArray,
4506 d3dx_effect_GetMatrixTransposeArray,
4507 d3dx_effect_SetMatrixTransposePointerArray,
4508 d3dx_effect_GetMatrixTransposePointerArray,
4509 d3dx_effect_SetString,
4510 d3dx_effect_GetString,
4511 d3dx_effect_SetTexture,
4512 d3dx_effect_GetTexture,
4513 d3dx_effect_GetPixelShader,
4514 d3dx_effect_GetVertexShader,
4515 d3dx_effect_SetArrayRange,
4516 /*** ID3DXEffect methods ***/
4517 d3dx_effect_GetPool,
4518 d3dx_effect_SetTechnique,
4519 d3dx_effect_GetCurrentTechnique,
4520 d3dx_effect_ValidateTechnique,
4521 d3dx_effect_FindNextValidTechnique,
4522 d3dx_effect_IsParameterUsed,
4523 d3dx_effect_Begin,
4524 d3dx_effect_BeginPass,
4525 d3dx_effect_CommitChanges,
4526 d3dx_effect_EndPass,
4527 d3dx_effect_End,
4528 d3dx_effect_GetDevice,
4529 d3dx_effect_OnLostDevice,
4530 d3dx_effect_OnResetDevice,
4531 d3dx_effect_SetStateManager,
4532 d3dx_effect_GetStateManager,
4533 d3dx_effect_BeginParameterBlock,
4534 d3dx_effect_EndParameterBlock,
4535 d3dx_effect_ApplyParameterBlock,
4536 #if D3DX_SDK_VERSION >= 26
4537 d3dx_effect_DeleteParameterBlock,
4538 #endif
4539 d3dx_effect_CloneEffect,
4540 #if D3DX_SDK_VERSION >= 27
4541 d3dx_effect_SetRawValue
4542 #endif
4545 static inline struct ID3DXEffectCompilerImpl *impl_from_ID3DXEffectCompiler(ID3DXEffectCompiler *iface)
4547 return CONTAINING_RECORD(iface, struct ID3DXEffectCompilerImpl, ID3DXEffectCompiler_iface);
4550 /*** IUnknown methods ***/
4551 static HRESULT WINAPI ID3DXEffectCompilerImpl_QueryInterface(ID3DXEffectCompiler *iface, REFIID riid, void **object)
4553 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
4555 if (IsEqualGUID(riid, &IID_IUnknown)
4556 || IsEqualGUID(riid, &IID_ID3DXEffectCompiler))
4558 iface->lpVtbl->AddRef(iface);
4559 *object = iface;
4560 return S_OK;
4563 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
4565 *object = NULL;
4566 return E_NOINTERFACE;
4569 static ULONG WINAPI ID3DXEffectCompilerImpl_AddRef(ID3DXEffectCompiler *iface)
4571 struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface);
4572 ULONG refcount = InterlockedIncrement(&compiler->ref);
4574 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
4576 return refcount;
4579 static ULONG WINAPI ID3DXEffectCompilerImpl_Release(ID3DXEffectCompiler *iface)
4581 struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface);
4582 ULONG refcount = InterlockedDecrement(&compiler->ref);
4584 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
4586 if (!refcount)
4588 free(compiler);
4591 return refcount;
4594 /*** ID3DXBaseEffect methods ***/
4595 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetDesc(ID3DXEffectCompiler *iface, D3DXEFFECT_DESC *desc)
4597 FIXME("iface %p, desc %p stub!\n", iface, desc);
4599 return E_NOTIMPL;
4602 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetParameterDesc(ID3DXEffectCompiler *iface,
4603 D3DXHANDLE parameter, D3DXPARAMETER_DESC *desc)
4605 FIXME("iface %p, parameter %p, desc %p stub!\n", iface, parameter, desc);
4607 return E_NOTIMPL;
4610 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetTechniqueDesc(ID3DXEffectCompiler *iface,
4611 D3DXHANDLE technique, D3DXTECHNIQUE_DESC *desc)
4613 FIXME("iface %p, technique %p, desc %p stub!\n", iface, technique, desc);
4615 return E_NOTIMPL;
4618 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetPassDesc(ID3DXEffectCompiler *iface,
4619 D3DXHANDLE pass, D3DXPASS_DESC *desc)
4621 FIXME("iface %p, pass %p, desc %p stub!\n", iface, pass, desc);
4623 return E_NOTIMPL;
4626 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFunctionDesc(ID3DXEffectCompiler *iface,
4627 D3DXHANDLE shader, D3DXFUNCTION_DESC *desc)
4629 FIXME("iface %p, shader %p, desc %p stub!\n", iface, shader, desc);
4631 return E_NOTIMPL;
4634 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameter(ID3DXEffectCompiler *iface,
4635 D3DXHANDLE parameter, UINT index)
4637 FIXME("iface %p, parameter %p, index %u stub!\n", iface, parameter, index);
4639 return NULL;
4642 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterByName(ID3DXEffectCompiler *iface,
4643 D3DXHANDLE parameter, const char *name)
4645 FIXME("iface %p, parameter %p, name %s stub!\n", iface, parameter, debugstr_a(name));
4647 return NULL;
4650 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterBySemantic(ID3DXEffectCompiler *iface,
4651 D3DXHANDLE parameter, const char *semantic)
4653 FIXME("iface %p, parameter %p, semantic %s stub!\n", iface, parameter, debugstr_a(semantic));
4655 return NULL;
4658 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterElement(ID3DXEffectCompiler *iface,
4659 D3DXHANDLE parameter, UINT index)
4661 FIXME("iface %p, parameter %p, index %u stub!\n", iface, parameter, index);
4663 return NULL;
4666 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetTechnique(ID3DXEffectCompiler *iface, UINT index)
4668 FIXME("iface %p, index %u stub!\n", iface, index);
4670 return NULL;
4673 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetTechniqueByName(ID3DXEffectCompiler *iface, const char *name)
4675 FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
4677 return NULL;
4680 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetPass(ID3DXEffectCompiler *iface, D3DXHANDLE technique, UINT index)
4682 FIXME("iface %p, technique %p, index %u stub!\n", iface, technique, index);
4684 return NULL;
4687 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetPassByName(ID3DXEffectCompiler *iface,
4688 D3DXHANDLE technique, const char *name)
4690 FIXME("iface %p, technique %p, name %s stub!\n", iface, technique, debugstr_a(name));
4692 return NULL;
4695 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetFunction(ID3DXEffectCompiler *iface, UINT index)
4697 FIXME("iface %p, index %u stub!\n", iface, index);
4699 return NULL;
4702 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetFunctionByName(ID3DXEffectCompiler *iface, const char *name)
4704 FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
4706 return NULL;
4709 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetAnnotation(ID3DXEffectCompiler *iface,
4710 D3DXHANDLE object, UINT index)
4712 FIXME("iface %p, object %p, index %u stub!\n", iface, object, index);
4714 return NULL;
4717 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetAnnotationByName(ID3DXEffectCompiler *iface,
4718 D3DXHANDLE object, const char *name)
4720 FIXME("iface %p, object %p, name %s stub!\n", iface, object, debugstr_a(name));
4722 return NULL;
4725 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetValue(ID3DXEffectCompiler *iface,
4726 D3DXHANDLE parameter, const void *data, UINT bytes)
4728 FIXME("iface %p, parameter %p, data %p, bytes %u stub!\n", iface, parameter, data, bytes);
4730 return E_NOTIMPL;
4733 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetValue(ID3DXEffectCompiler *iface,
4734 D3DXHANDLE parameter, void *data, UINT bytes)
4736 FIXME("iface %p, parameter %p, data %p, bytes %u stub!\n", iface, parameter, data, bytes);
4738 return E_NOTIMPL;
4741 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetBool(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL b)
4743 FIXME("iface %p, parameter %p, b %#x stub!\n", iface, parameter, b);
4745 return E_NOTIMPL;
4748 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetBool(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL *b)
4750 FIXME("iface %p, parameter %p, b %p stub!\n", iface, parameter, b);
4752 return E_NOTIMPL;
4755 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetBoolArray(ID3DXEffectCompiler *iface,
4756 D3DXHANDLE parameter, const BOOL *b, UINT count)
4758 FIXME("iface %p, parameter %p, b %p, count %u stub!\n", iface, parameter, b, count);
4760 return E_NOTIMPL;
4763 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetBoolArray(ID3DXEffectCompiler *iface,
4764 D3DXHANDLE parameter, BOOL *b, UINT count)
4766 FIXME("iface %p, parameter %p, b %p, count %u stub!\n", iface, parameter, b, count);
4768 return E_NOTIMPL;
4771 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetInt(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, INT n)
4773 FIXME("iface %p, parameter %p, n %d stub!\n", iface, parameter, n);
4775 return E_NOTIMPL;
4778 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetInt(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, INT *n)
4780 FIXME("iface %p, parameter %p, n %p stub!\n", iface, parameter, n);
4782 return E_NOTIMPL;
4785 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetIntArray(ID3DXEffectCompiler *iface,
4786 D3DXHANDLE parameter, const INT *n, UINT count)
4788 FIXME("iface %p, parameter %p, n %p, count %u stub!\n", iface, parameter, n, count);
4790 return E_NOTIMPL;
4793 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetIntArray(ID3DXEffectCompiler *iface,
4794 D3DXHANDLE parameter, INT *n, UINT count)
4796 FIXME("iface %p, parameter %p, n %p, count %u stub!\n", iface, parameter, n, count);
4798 return E_NOTIMPL;
4801 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetFloat(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, float f)
4803 FIXME("iface %p, parameter %p, f %.8e stub!\n", iface, parameter, f);
4805 return E_NOTIMPL;
4808 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFloat(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, float *f)
4810 FIXME("iface %p, parameter %p, f %p stub!\n", iface, parameter, f);
4812 return E_NOTIMPL;
4815 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetFloatArray(ID3DXEffectCompiler *iface,
4816 D3DXHANDLE parameter, const float *f, UINT count)
4818 FIXME("iface %p, parameter %p, f %p, count %u stub!\n", iface, parameter, f, count);
4820 return E_NOTIMPL;
4823 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFloatArray(ID3DXEffectCompiler *iface,
4824 D3DXHANDLE parameter, float *f, UINT count)
4826 FIXME("iface %p, parameter %p, f %p, count %u stub!\n", iface, parameter, f, count);
4828 return E_NOTIMPL;
4831 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetVector(ID3DXEffectCompiler *iface,
4832 D3DXHANDLE parameter, const D3DXVECTOR4 *vector)
4834 FIXME("iface %p, parameter %p, vector %p stub!\n", iface, parameter, vector);
4836 return E_NOTIMPL;
4839 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVector(ID3DXEffectCompiler *iface,
4840 D3DXHANDLE parameter, D3DXVECTOR4 *vector)
4842 FIXME("iface %p, parameter %p, vector %p stub!\n", iface, parameter, vector);
4844 return E_NOTIMPL;
4847 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetVectorArray(ID3DXEffectCompiler *iface,
4848 D3DXHANDLE parameter, const D3DXVECTOR4 *vector, UINT count)
4850 FIXME("iface %p, parameter %p, vector %p, count %u stub!\n", iface, parameter, vector, count);
4852 return E_NOTIMPL;
4855 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVectorArray(ID3DXEffectCompiler *iface,
4856 D3DXHANDLE parameter, D3DXVECTOR4 *vector, UINT count)
4858 FIXME("iface %p, parameter %p, vector %p, count %u stub!\n", iface, parameter, vector, count);
4860 return E_NOTIMPL;
4863 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrix(ID3DXEffectCompiler *iface,
4864 D3DXHANDLE parameter, const D3DXMATRIX *matrix)
4866 FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
4868 return E_NOTIMPL;
4871 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrix(ID3DXEffectCompiler *iface,
4872 D3DXHANDLE parameter, D3DXMATRIX *matrix)
4874 FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
4876 return E_NOTIMPL;
4879 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixArray(ID3DXEffectCompiler *iface,
4880 D3DXHANDLE parameter, const D3DXMATRIX *matrix, UINT count)
4882 FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4884 return E_NOTIMPL;
4887 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixArray(ID3DXEffectCompiler *iface,
4888 D3DXHANDLE parameter, D3DXMATRIX *matrix, UINT count)
4890 FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4892 return E_NOTIMPL;
4895 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixPointerArray(ID3DXEffectCompiler *iface,
4896 D3DXHANDLE parameter, const D3DXMATRIX **matrix, UINT count)
4898 FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4900 return E_NOTIMPL;
4903 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixPointerArray(ID3DXEffectCompiler *iface,
4904 D3DXHANDLE parameter, D3DXMATRIX **matrix, UINT count)
4906 FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4908 return E_NOTIMPL;
4911 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTranspose(ID3DXEffectCompiler *iface,
4912 D3DXHANDLE parameter, const D3DXMATRIX *matrix)
4914 FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
4916 return E_NOTIMPL;
4919 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTranspose(ID3DXEffectCompiler *iface,
4920 D3DXHANDLE parameter, D3DXMATRIX *matrix)
4922 FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
4924 return E_NOTIMPL;
4927 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTransposeArray(ID3DXEffectCompiler *iface,
4928 D3DXHANDLE parameter, const D3DXMATRIX *matrix, UINT count)
4930 FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4932 return E_NOTIMPL;
4935 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTransposeArray(ID3DXEffectCompiler *iface,
4936 D3DXHANDLE parameter, D3DXMATRIX *matrix, UINT count)
4938 FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4940 return E_NOTIMPL;
4943 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTransposePointerArray(ID3DXEffectCompiler *iface,
4944 D3DXHANDLE parameter, const D3DXMATRIX **matrix, UINT count)
4946 FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4948 return E_NOTIMPL;
4951 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTransposePointerArray(ID3DXEffectCompiler *iface,
4952 D3DXHANDLE parameter, D3DXMATRIX **matrix, UINT count)
4954 FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4956 return E_NOTIMPL;
4959 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetString(ID3DXEffectCompiler *iface,
4960 D3DXHANDLE parameter, const char *string)
4962 FIXME("iface %p, parameter %p, string %s stub!\n", iface, parameter, debugstr_a(string));
4964 return E_NOTIMPL;
4967 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetString(ID3DXEffectCompiler *iface,
4968 D3DXHANDLE parameter, const char **string)
4970 FIXME("iface %p, parameter %p, string %p stub!\n", iface, parameter, string);
4972 return E_NOTIMPL;
4975 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetTexture(struct ID3DXEffectCompiler *iface,
4976 D3DXHANDLE parameter, struct IDirect3DBaseTexture9 *texture)
4978 FIXME("iface %p, parameter %p, texture %p stub!\n", iface, parameter, texture);
4980 return E_NOTIMPL;
4983 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetTexture(struct ID3DXEffectCompiler *iface,
4984 D3DXHANDLE parameter, struct IDirect3DBaseTexture9 **texture)
4986 FIXME("iface %p, parameter %p, texture %p stub!\n", iface, parameter, texture);
4988 return E_NOTIMPL;
4991 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetPixelShader(ID3DXEffectCompiler *iface,
4992 D3DXHANDLE parameter, struct IDirect3DPixelShader9 **shader)
4994 FIXME("iface %p, parameter %p, shader %p stub!\n", iface, parameter, shader);
4996 return E_NOTIMPL;
4999 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVertexShader(struct ID3DXEffectCompiler *iface,
5000 D3DXHANDLE parameter, struct IDirect3DVertexShader9 **shader)
5002 FIXME("iface %p, parameter %p, shader %p stub!\n", iface, parameter, shader);
5004 return E_NOTIMPL;
5007 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetArrayRange(ID3DXEffectCompiler *iface,
5008 D3DXHANDLE parameter, UINT start, UINT end)
5010 FIXME("iface %p, parameter %p, start %u, end %u stub!\n", iface, parameter, start, end);
5012 return E_NOTIMPL;
5015 /*** ID3DXEffectCompiler methods ***/
5016 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetLiteral(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL literal)
5018 FIXME("iface %p, parameter %p, literal %#x stub!\n", iface, parameter, literal);
5020 return E_NOTIMPL;
5023 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetLiteral(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL *literal)
5025 FIXME("iface %p, parameter %p, literal %p stub!\n", iface, parameter, literal);
5027 return E_NOTIMPL;
5030 static HRESULT WINAPI ID3DXEffectCompilerImpl_CompileEffect(ID3DXEffectCompiler *iface, DWORD flags,
5031 ID3DXBuffer **effect, ID3DXBuffer **error_msgs)
5033 FIXME("iface %p, flags %#lx, effect %p, error_msgs %p stub!\n", iface, flags, effect, error_msgs);
5035 return E_NOTIMPL;
5038 static HRESULT WINAPI ID3DXEffectCompilerImpl_CompileShader(ID3DXEffectCompiler *iface, D3DXHANDLE function,
5039 const char *target, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_msgs,
5040 ID3DXConstantTable **constant_table)
5042 FIXME("iface %p, function %p, target %s, flags %#lx, shader %p, error_msgs %p, constant_table %p stub!\n",
5043 iface, function, debugstr_a(target), flags, shader, error_msgs, constant_table);
5045 return E_NOTIMPL;
5048 static const struct ID3DXEffectCompilerVtbl ID3DXEffectCompiler_Vtbl =
5050 /*** IUnknown methods ***/
5051 ID3DXEffectCompilerImpl_QueryInterface,
5052 ID3DXEffectCompilerImpl_AddRef,
5053 ID3DXEffectCompilerImpl_Release,
5054 /*** ID3DXBaseEffect methods ***/
5055 ID3DXEffectCompilerImpl_GetDesc,
5056 ID3DXEffectCompilerImpl_GetParameterDesc,
5057 ID3DXEffectCompilerImpl_GetTechniqueDesc,
5058 ID3DXEffectCompilerImpl_GetPassDesc,
5059 ID3DXEffectCompilerImpl_GetFunctionDesc,
5060 ID3DXEffectCompilerImpl_GetParameter,
5061 ID3DXEffectCompilerImpl_GetParameterByName,
5062 ID3DXEffectCompilerImpl_GetParameterBySemantic,
5063 ID3DXEffectCompilerImpl_GetParameterElement,
5064 ID3DXEffectCompilerImpl_GetTechnique,
5065 ID3DXEffectCompilerImpl_GetTechniqueByName,
5066 ID3DXEffectCompilerImpl_GetPass,
5067 ID3DXEffectCompilerImpl_GetPassByName,
5068 ID3DXEffectCompilerImpl_GetFunction,
5069 ID3DXEffectCompilerImpl_GetFunctionByName,
5070 ID3DXEffectCompilerImpl_GetAnnotation,
5071 ID3DXEffectCompilerImpl_GetAnnotationByName,
5072 ID3DXEffectCompilerImpl_SetValue,
5073 ID3DXEffectCompilerImpl_GetValue,
5074 ID3DXEffectCompilerImpl_SetBool,
5075 ID3DXEffectCompilerImpl_GetBool,
5076 ID3DXEffectCompilerImpl_SetBoolArray,
5077 ID3DXEffectCompilerImpl_GetBoolArray,
5078 ID3DXEffectCompilerImpl_SetInt,
5079 ID3DXEffectCompilerImpl_GetInt,
5080 ID3DXEffectCompilerImpl_SetIntArray,
5081 ID3DXEffectCompilerImpl_GetIntArray,
5082 ID3DXEffectCompilerImpl_SetFloat,
5083 ID3DXEffectCompilerImpl_GetFloat,
5084 ID3DXEffectCompilerImpl_SetFloatArray,
5085 ID3DXEffectCompilerImpl_GetFloatArray,
5086 ID3DXEffectCompilerImpl_SetVector,
5087 ID3DXEffectCompilerImpl_GetVector,
5088 ID3DXEffectCompilerImpl_SetVectorArray,
5089 ID3DXEffectCompilerImpl_GetVectorArray,
5090 ID3DXEffectCompilerImpl_SetMatrix,
5091 ID3DXEffectCompilerImpl_GetMatrix,
5092 ID3DXEffectCompilerImpl_SetMatrixArray,
5093 ID3DXEffectCompilerImpl_GetMatrixArray,
5094 ID3DXEffectCompilerImpl_SetMatrixPointerArray,
5095 ID3DXEffectCompilerImpl_GetMatrixPointerArray,
5096 ID3DXEffectCompilerImpl_SetMatrixTranspose,
5097 ID3DXEffectCompilerImpl_GetMatrixTranspose,
5098 ID3DXEffectCompilerImpl_SetMatrixTransposeArray,
5099 ID3DXEffectCompilerImpl_GetMatrixTransposeArray,
5100 ID3DXEffectCompilerImpl_SetMatrixTransposePointerArray,
5101 ID3DXEffectCompilerImpl_GetMatrixTransposePointerArray,
5102 ID3DXEffectCompilerImpl_SetString,
5103 ID3DXEffectCompilerImpl_GetString,
5104 ID3DXEffectCompilerImpl_SetTexture,
5105 ID3DXEffectCompilerImpl_GetTexture,
5106 ID3DXEffectCompilerImpl_GetPixelShader,
5107 ID3DXEffectCompilerImpl_GetVertexShader,
5108 ID3DXEffectCompilerImpl_SetArrayRange,
5109 /*** ID3DXEffectCompiler methods ***/
5110 ID3DXEffectCompilerImpl_SetLiteral,
5111 ID3DXEffectCompilerImpl_GetLiteral,
5112 ID3DXEffectCompilerImpl_CompileEffect,
5113 ID3DXEffectCompilerImpl_CompileShader,
5116 static HRESULT d3dx_parse_sampler(struct d3dx_effect *effect, struct d3dx_sampler *sampler,
5117 const char *data, const char **ptr, struct d3dx_object *objects)
5119 HRESULT hr;
5120 UINT i;
5122 sampler->state_count = read_u32(ptr);
5123 TRACE("Count: %u\n", sampler->state_count);
5125 sampler->states = calloc(sampler->state_count, sizeof(*sampler->states));
5126 if (!sampler->states)
5128 ERR("Out of memory\n");
5129 return E_OUTOFMEMORY;
5132 for (i = 0; i < sampler->state_count; ++i)
5134 hr = d3dx_parse_state(effect, &sampler->states[i], data, ptr, objects);
5135 if (hr != D3D_OK)
5137 WARN("Failed to parse state %u\n", i);
5138 goto err_out;
5142 return D3D_OK;
5144 err_out:
5146 for (i = 0; i < sampler->state_count; ++i)
5148 free_state(&sampler->states[i]);
5150 free(sampler->states);
5151 sampler->states = NULL;
5153 return hr;
5156 static HRESULT d3dx_parse_value(struct d3dx_effect *effect, struct d3dx_parameter *param,
5157 void *value, const char *data, const char **ptr, struct d3dx_object *objects)
5159 unsigned int i;
5160 HRESULT hr;
5161 UINT old_size = 0;
5163 if (param->element_count)
5165 param->data = value;
5167 for (i = 0; i < param->element_count; ++i)
5169 struct d3dx_parameter *member = &param->members[i];
5171 hr = d3dx_parse_value(effect, member, value ? (char *)value + old_size : NULL, data, ptr, objects);
5172 if (hr != D3D_OK)
5174 WARN("Failed to parse value %u\n", i);
5175 return hr;
5178 old_size += member->bytes;
5181 return D3D_OK;
5184 switch(param->class)
5186 case D3DXPC_SCALAR:
5187 case D3DXPC_VECTOR:
5188 case D3DXPC_MATRIX_ROWS:
5189 case D3DXPC_MATRIX_COLUMNS:
5190 param->data = value;
5191 break;
5193 case D3DXPC_STRUCT:
5194 param->data = value;
5196 for (i = 0; i < param->member_count; ++i)
5198 struct d3dx_parameter *member = &param->members[i];
5200 hr = d3dx_parse_value(effect, member, (char *)value + old_size, data, ptr, objects);
5201 if (hr != D3D_OK)
5203 WARN("Failed to parse value %u\n", i);
5204 return hr;
5207 old_size += member->bytes;
5209 break;
5211 case D3DXPC_OBJECT:
5212 switch (param->type)
5214 case D3DXPT_STRING:
5215 case D3DXPT_TEXTURE:
5216 case D3DXPT_TEXTURE1D:
5217 case D3DXPT_TEXTURE2D:
5218 case D3DXPT_TEXTURE3D:
5219 case D3DXPT_TEXTURECUBE:
5220 case D3DXPT_PIXELSHADER:
5221 case D3DXPT_VERTEXSHADER:
5222 param->object_id = read_u32(ptr);
5223 TRACE("Id: %u\n", param->object_id);
5224 objects[param->object_id].param = param;
5225 param->data = value;
5226 break;
5228 case D3DXPT_SAMPLER:
5229 case D3DXPT_SAMPLER1D:
5230 case D3DXPT_SAMPLER2D:
5231 case D3DXPT_SAMPLER3D:
5232 case D3DXPT_SAMPLERCUBE:
5234 struct d3dx_sampler *sampler;
5236 sampler = calloc(1, sizeof(*sampler));
5237 if (!sampler)
5238 return E_OUTOFMEMORY;
5240 hr = d3dx_parse_sampler(effect, sampler, data, ptr, objects);
5241 if (hr != D3D_OK)
5243 free(sampler);
5244 WARN("Failed to parse sampler\n");
5245 return hr;
5248 param->data = sampler;
5249 break;
5252 default:
5253 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(param->type));
5254 break;
5256 break;
5258 default:
5259 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
5260 break;
5263 return D3D_OK;
5266 static HRESULT d3dx_parse_init_value(struct d3dx_effect *effect, struct d3dx_parameter *param,
5267 const char *data, const char *ptr, struct d3dx_object *objects)
5269 UINT size = param->bytes;
5270 HRESULT hr;
5271 void *value = NULL;
5273 TRACE("param size: %u\n", size);
5275 if (size)
5277 value = calloc(1, size);
5278 if (!value)
5280 ERR("Failed to allocate data memory.\n");
5281 return E_OUTOFMEMORY;
5284 switch(param->class)
5286 case D3DXPC_OBJECT:
5287 break;
5289 case D3DXPC_SCALAR:
5290 case D3DXPC_VECTOR:
5291 case D3DXPC_MATRIX_ROWS:
5292 case D3DXPC_MATRIX_COLUMNS:
5293 case D3DXPC_STRUCT:
5294 TRACE("Data: %s.\n", debugstr_an(ptr, size));
5295 memcpy(value, ptr, size);
5296 break;
5298 default:
5299 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
5300 break;
5304 hr = d3dx_parse_value(effect, param, value, data, &ptr, objects);
5305 if (hr != D3D_OK)
5307 WARN("Failed to parse value\n");
5308 free(value);
5309 return hr;
5312 return D3D_OK;
5315 static HRESULT d3dx9_parse_name(char **name, const char *ptr)
5317 unsigned int size;
5319 size = read_u32(&ptr);
5320 TRACE("Name size: %#x.\n", size);
5322 if (!size)
5324 return D3D_OK;
5327 *name = malloc(size);
5328 if (!*name)
5330 ERR("Failed to allocate name memory.\n");
5331 return E_OUTOFMEMORY;
5334 TRACE("Name: %s.\n", debugstr_an(ptr, size));
5335 memcpy(*name, ptr, size);
5337 return D3D_OK;
5340 static HRESULT d3dx9_copy_data(struct d3dx_effect *effect, unsigned int object_id, const char **ptr)
5342 struct d3dx_object *object = &effect->objects[object_id];
5344 if (object->size || object->data)
5346 if (object_id)
5347 FIXME("Overwriting object id %u!\n", object_id);
5348 else
5349 TRACE("Overwriting object id 0.\n");
5351 free(object->data);
5352 object->data = NULL;
5355 object->size = read_u32(ptr);
5356 TRACE("Data size: %#x.\n", object->size);
5358 if (!object->size)
5359 return D3D_OK;
5361 object->data = malloc(object->size);
5362 if (!object->data)
5364 ERR("Failed to allocate object memory.\n");
5365 return E_OUTOFMEMORY;
5368 TRACE("Data: %s.\n", debugstr_an(*ptr, object->size));
5369 memcpy(object->data, *ptr, object->size);
5371 *ptr += ((object->size + 3) & ~3);
5373 return D3D_OK;
5376 static void param_set_magic_number(struct d3dx_parameter *param)
5378 memcpy(param->magic_string, parameter_magic_string, sizeof(parameter_magic_string));
5381 static void add_param_to_tree(struct d3dx_effect *effect, struct d3dx_parameter *param,
5382 struct d3dx_parameter *parent, char separator, unsigned int element)
5384 const char *parent_name = parent ? parent->full_name : NULL;
5385 unsigned int i;
5387 TRACE("Adding parameter %p (%s - parent %p, element %u) to the rbtree.\n",
5388 param, debugstr_a(param->name), parent, element);
5390 if (parent_name)
5392 unsigned int parent_name_len = strlen(parent_name);
5393 unsigned int name_len = strlen(param->name);
5394 unsigned int part_str_len;
5395 unsigned int len;
5396 char part_str[16];
5398 if (separator == '[')
5400 sprintf(part_str, "[%u]", element);
5401 part_str_len = strlen(part_str);
5402 name_len = 0;
5404 else
5406 part_str[0] = separator;
5407 part_str[1] = 0;
5408 part_str_len = 1;
5410 len = parent_name_len + part_str_len + name_len + 1;
5412 if (!(param->full_name = malloc(len)))
5414 ERR("Out of memory.\n");
5415 return;
5418 memcpy(param->full_name, parent_name, parent_name_len);
5419 memcpy(param->full_name + parent_name_len, part_str, part_str_len);
5420 memcpy(param->full_name + parent_name_len + part_str_len, param->name, name_len);
5421 param->full_name[len - 1] = 0;
5423 else
5425 if (!(param->full_name = strdup(param->name)))
5427 ERR("Out of memory.\n");
5428 return;
5431 TRACE("Full name is %s.\n", param->full_name);
5432 wine_rb_put(&effect->params.tree, param->full_name, &param->rb_entry);
5434 if (is_top_level_parameter(param))
5435 for (i = 0; i < param->top_level_param->annotation_count; ++i)
5436 add_param_to_tree(effect, &param->top_level_param->annotations[i], param, '@', 0);
5438 if (param->element_count)
5439 for (i = 0; i < param->element_count; ++i)
5440 add_param_to_tree(effect, &param->members[i], param, '[', i);
5441 else
5442 for (i = 0; i < param->member_count; ++i)
5443 add_param_to_tree(effect, &param->members[i], param, '.', 0);
5446 static HRESULT d3dx_parse_effect_typedef(struct d3dx_effect *effect, struct d3dx_parameter *param,
5447 const char *data, const char **ptr, struct d3dx_parameter *parent, UINT flags)
5449 uint32_t offset;
5450 HRESULT hr;
5451 UINT i;
5453 param->flags = flags;
5455 if (!parent)
5457 param->type = read_u32(ptr);
5458 TRACE("Type: %s.\n", debug_d3dxparameter_type(param->type));
5460 param->class = read_u32(ptr);
5461 TRACE("Class: %s.\n", debug_d3dxparameter_class(param->class));
5463 offset = read_u32(ptr);
5464 TRACE("Type name offset: %#x.\n", offset);
5465 hr = d3dx9_parse_name(&param->name, data + offset);
5466 if (hr != D3D_OK)
5468 WARN("Failed to parse name\n");
5469 goto err_out;
5472 offset = read_u32(ptr);
5473 TRACE("Type semantic offset: %#x.\n", offset);
5474 hr = d3dx9_parse_name(&param->semantic, data + offset);
5475 if (hr != D3D_OK)
5477 WARN("Failed to parse semantic\n");
5478 goto err_out;
5481 param->element_count = read_u32(ptr);
5482 TRACE("Elements: %u.\n", param->element_count);
5484 switch (param->class)
5486 case D3DXPC_VECTOR:
5487 param->columns = read_u32(ptr);
5488 TRACE("Columns: %u.\n", param->columns);
5490 param->rows = read_u32(ptr);
5491 TRACE("Rows: %u.\n", param->rows);
5493 /* sizeof(DWORD) * rows * columns */
5494 param->bytes = 4 * param->rows * param->columns;
5495 break;
5497 case D3DXPC_SCALAR:
5498 case D3DXPC_MATRIX_ROWS:
5499 case D3DXPC_MATRIX_COLUMNS:
5500 param->rows = read_u32(ptr);
5501 TRACE("Rows: %u.\n", param->rows);
5503 param->columns = read_u32(ptr);
5504 TRACE("Columns: %u.\n", param->columns);
5506 /* sizeof(DWORD) * rows * columns */
5507 param->bytes = 4 * param->rows * param->columns;
5508 break;
5510 case D3DXPC_STRUCT:
5511 param->member_count = read_u32(ptr);
5512 TRACE("Members: %u.\n", param->member_count);
5513 break;
5515 case D3DXPC_OBJECT:
5516 switch (param->type)
5518 case D3DXPT_STRING:
5519 case D3DXPT_PIXELSHADER:
5520 case D3DXPT_VERTEXSHADER:
5521 case D3DXPT_TEXTURE:
5522 case D3DXPT_TEXTURE1D:
5523 case D3DXPT_TEXTURE2D:
5524 case D3DXPT_TEXTURE3D:
5525 case D3DXPT_TEXTURECUBE:
5526 param->bytes = sizeof(void *);
5527 break;
5529 case D3DXPT_SAMPLER:
5530 case D3DXPT_SAMPLER1D:
5531 case D3DXPT_SAMPLER2D:
5532 case D3DXPT_SAMPLER3D:
5533 case D3DXPT_SAMPLERCUBE:
5534 param->bytes = 0;
5535 break;
5537 default:
5538 FIXME("Unhandled type %s.\n", debug_d3dxparameter_type(param->type));
5539 break;
5541 break;
5543 default:
5544 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
5545 break;
5548 else
5550 /* elements */
5551 param->type = parent->type;
5552 param->class = parent->class;
5553 param->name = parent->name;
5554 param->semantic = parent->semantic;
5555 param->element_count = 0;
5556 param->member_count = parent->member_count;
5557 param->bytes = parent->bytes;
5558 param->rows = parent->rows;
5559 param->columns = parent->columns;
5562 if (param->element_count)
5564 unsigned int param_bytes = 0;
5565 const char *save_ptr = *ptr;
5567 param->members = calloc(param->element_count, sizeof(*param->members));
5568 if (!param->members)
5570 ERR("Out of memory\n");
5571 hr = E_OUTOFMEMORY;
5572 goto err_out;
5575 for (i = 0; i < param->element_count; ++i)
5577 *ptr = save_ptr;
5579 param_set_magic_number(&param->members[i]);
5580 hr = d3dx_parse_effect_typedef(effect, &param->members[i], data, ptr, param, flags);
5581 if (hr != D3D_OK)
5583 WARN("Failed to parse member %u\n", i);
5584 goto err_out;
5587 param_bytes += param->members[i].bytes;
5590 param->bytes = param_bytes;
5592 else if (param->member_count)
5594 param->members = calloc(param->member_count, sizeof(*param->members));
5595 if (!param->members)
5597 ERR("Out of memory\n");
5598 hr = E_OUTOFMEMORY;
5599 goto err_out;
5602 for (i = 0; i < param->member_count; ++i)
5604 param_set_magic_number(&param->members[i]);
5605 hr = d3dx_parse_effect_typedef(effect, &param->members[i], data, ptr, NULL, flags);
5606 if (hr != D3D_OK)
5608 WARN("Failed to parse member %u\n", i);
5609 goto err_out;
5612 param->bytes += param->members[i].bytes;
5615 return D3D_OK;
5617 err_out:
5619 if (param->members)
5621 unsigned int count = param->element_count ? param->element_count : param->member_count;
5623 for (i = 0; i < count; ++i)
5624 free_parameter(&param->members[i], param->element_count != 0, TRUE);
5625 free(param->members);
5626 param->members = NULL;
5629 if (!parent)
5631 free(param->name);
5632 free(param->semantic);
5634 param->name = NULL;
5635 param->semantic = NULL;
5637 return hr;
5640 static HRESULT d3dx_parse_effect_annotation(struct d3dx_effect *effect, struct d3dx_parameter *anno,
5641 const char *data, const char **ptr, struct d3dx_object *objects)
5643 const char *ptr2;
5644 uint32_t offset;
5645 HRESULT hr;
5647 anno->flags = D3DX_PARAMETER_ANNOTATION;
5649 offset = read_u32(ptr);
5650 TRACE("Typedef offset: %#x.\n", offset);
5651 ptr2 = data + offset;
5652 hr = d3dx_parse_effect_typedef(effect, anno, data, &ptr2, NULL, D3DX_PARAMETER_ANNOTATION);
5653 if (hr != D3D_OK)
5655 WARN("Failed to parse type definition.\n");
5656 return hr;
5659 offset = read_u32(ptr);
5660 TRACE("Value offset: %#x.\n", offset);
5661 hr = d3dx_parse_init_value(effect, anno, data, data + offset, objects);
5662 if (hr != D3D_OK)
5664 WARN("Failed to parse value.\n");
5665 return hr;
5668 return D3D_OK;
5671 static HRESULT d3dx_parse_state(struct d3dx_effect *effect, struct d3dx_state *state,
5672 const char *data, const char **ptr, struct d3dx_object *objects)
5674 struct d3dx_parameter *param = &state->parameter;
5675 enum STATE_CLASS state_class;
5676 const char *ptr2;
5677 uint32_t offset;
5678 void *new_data;
5679 HRESULT hr;
5681 state->type = ST_CONSTANT;
5683 state->operation = read_u32(ptr);
5684 if (state->operation >= ARRAY_SIZE(state_table))
5686 WARN("Unknown state operation %u.\n", state->operation);
5687 return D3DERR_INVALIDCALL;
5689 TRACE("Operation: %#x (%s).\n", state->operation, state_table[state->operation].name);
5691 state->index = read_u32(ptr);
5692 TRACE("Index: %#x.\n", state->index);
5694 offset = read_u32(ptr);
5695 TRACE("Typedef offset: %#x.\n", offset);
5696 ptr2 = data + offset;
5697 hr = d3dx_parse_effect_typedef(effect, param, data, &ptr2, NULL, 0);
5698 if (hr != D3D_OK)
5700 WARN("Failed to parse type definition\n");
5701 goto err_out;
5704 offset = read_u32(ptr);
5705 TRACE("Value offset: %#x.\n", offset);
5706 hr = d3dx_parse_init_value(effect, param, data, data + offset, objects);
5707 if (hr != D3D_OK)
5709 WARN("Failed to parse value\n");
5710 goto err_out;
5713 if (((state_class = state_table[state->operation].class) == SC_VERTEXSHADER
5714 || state_class == SC_PIXELSHADER || state_class == SC_TEXTURE)
5715 && param->bytes < sizeof(void *))
5717 if (param->type != D3DXPT_INT || *(unsigned int *)param->data)
5719 FIXME("Unexpected parameter for object, param->type %#x, param->class %#x, *param->data %#x.\n",
5720 param->type, param->class, *(unsigned int *)param->data);
5721 hr = D3DXERR_INVALIDDATA;
5722 goto err_out;
5725 new_data = realloc(param->data, sizeof(void *));
5726 if (!new_data)
5728 ERR("Out of memory.\n");
5729 hr = E_OUTOFMEMORY;
5730 goto err_out;
5732 memset(new_data, 0, sizeof(void *));
5733 param->data = new_data;
5734 param->bytes = sizeof(void *);
5737 return D3D_OK;
5739 err_out:
5741 free_parameter(param, FALSE, FALSE);
5743 return hr;
5746 static HRESULT d3dx_parse_effect_parameter(struct d3dx_effect *effect, struct d3dx_top_level_parameter *param,
5747 const char *data, const char **ptr, struct d3dx_object *objects)
5749 const char *ptr2;
5750 uint32_t offset;
5751 unsigned int i;
5752 HRESULT hr;
5754 offset = read_u32(ptr);
5755 TRACE("Typedef offset: %#x.\n", offset);
5756 ptr2 = data + offset;
5758 offset = read_u32(ptr);
5759 TRACE("Value offset: %#x.\n", offset);
5761 param->param.flags = read_u32(ptr);
5762 TRACE("Flags: %#x.\n", param->param.flags);
5764 param->annotation_count = read_u32(ptr);
5765 TRACE("Annotation count: %u.\n", param->annotation_count);
5767 hr = d3dx_parse_effect_typedef(effect, &param->param, data, &ptr2, NULL, param->param.flags);
5768 if (hr != D3D_OK)
5770 WARN("Failed to parse type definition.\n");
5771 return hr;
5774 hr = d3dx_parse_init_value(effect, &param->param, data, data + offset, objects);
5775 if (hr != D3D_OK)
5777 WARN("Failed to parse value.\n");
5778 return hr;
5781 if (param->annotation_count)
5783 param->annotations = calloc(param->annotation_count, sizeof(*param->annotations));
5784 if (!param->annotations)
5786 ERR("Out of memory.\n");
5787 hr = E_OUTOFMEMORY;
5788 goto err_out;
5791 for (i = 0; i < param->annotation_count; ++i)
5793 param_set_magic_number(&param->annotations[i]);
5794 hr = d3dx_parse_effect_annotation(effect, &param->annotations[i], data, ptr, objects);
5795 if (hr != D3D_OK)
5797 WARN("Failed to parse annotation.\n");
5798 goto err_out;
5803 return D3D_OK;
5805 err_out:
5807 if (param->annotations)
5809 for (i = 0; i < param->annotation_count; ++i)
5810 free_parameter(&param->annotations[i], FALSE, FALSE);
5811 free(param->annotations);
5812 param->annotations = NULL;
5815 return hr;
5818 static HRESULT d3dx_parse_effect_pass(struct d3dx_effect *effect, struct d3dx_pass *pass,
5819 const char *data, const char **ptr, struct d3dx_object *objects)
5821 struct d3dx_state *states = NULL;
5822 char *name = NULL;
5823 uint32_t offset;
5824 unsigned int i;
5825 HRESULT hr;
5827 offset = read_u32(ptr);
5828 TRACE("Pass name offset: %#x.\n", offset);
5829 hr = d3dx9_parse_name(&name, data + offset);
5830 if (hr != D3D_OK)
5832 WARN("Failed to parse name.\n");
5833 goto err_out;
5836 pass->annotation_count = read_u32(ptr);
5837 TRACE("Annotation count: %u.\n", pass->annotation_count);
5839 pass->state_count = read_u32(ptr);
5840 TRACE("State count: %u.\n", pass->state_count);
5842 if (pass->annotation_count)
5844 pass->annotations = calloc(pass->annotation_count, sizeof(*pass->annotations));
5845 if (!pass->annotations)
5847 ERR("Out of memory\n");
5848 hr = E_OUTOFMEMORY;
5849 goto err_out;
5852 for (i = 0; i < pass->annotation_count; ++i)
5854 param_set_magic_number(&pass->annotations[i]);
5855 hr = d3dx_parse_effect_annotation(effect, &pass->annotations[i], data, ptr, objects);
5856 if (hr != D3D_OK)
5858 WARN("Failed to parse annotation %u\n", i);
5859 goto err_out;
5864 if (pass->state_count)
5866 states = calloc(pass->state_count, sizeof(*states));
5867 if (!states)
5869 ERR("Out of memory\n");
5870 hr = E_OUTOFMEMORY;
5871 goto err_out;
5874 for (i = 0; i < pass->state_count; ++i)
5876 hr = d3dx_parse_state(effect, &states[i], data, ptr, objects);
5877 if (hr != D3D_OK)
5879 WARN("Failed to parse annotation %u\n", i);
5880 goto err_out;
5885 pass->name = name;
5886 pass->states = states;
5888 return D3D_OK;
5890 err_out:
5892 if (pass->annotations)
5894 for (i = 0; i < pass->annotation_count; ++i)
5895 free_parameter(&pass->annotations[i], FALSE, FALSE);
5896 free(pass->annotations);
5897 pass->annotations = NULL;
5900 if (states)
5902 for (i = 0; i < pass->state_count; ++i)
5904 free_state(&states[i]);
5906 free(states);
5909 free(name);
5911 return hr;
5914 static HRESULT d3dx_parse_effect_technique(struct d3dx_effect *effect, struct d3dx_technique *technique,
5915 const char *data, const char **ptr, struct d3dx_object *objects)
5917 char *name = NULL;
5918 uint32_t offset;
5919 unsigned int i;
5920 HRESULT hr;
5922 offset = read_u32(ptr);
5923 TRACE("Technique name offset: %#x.\n", offset);
5924 hr = d3dx9_parse_name(&name, data + offset);
5925 if (hr != D3D_OK)
5927 WARN("Failed to parse name\n");
5928 goto err_out;
5931 technique->annotation_count = read_u32(ptr);
5932 TRACE("Annotation count: %u.\n", technique->annotation_count);
5934 technique->pass_count = read_u32(ptr);
5935 TRACE("Pass count: %u.\n", technique->pass_count);
5937 if (technique->annotation_count)
5939 technique->annotations = calloc(technique->annotation_count, sizeof(*technique->annotations));
5940 if (!technique->annotations)
5942 ERR("Out of memory\n");
5943 hr = E_OUTOFMEMORY;
5944 goto err_out;
5947 for (i = 0; i < technique->annotation_count; ++i)
5949 param_set_magic_number(&technique->annotations[i]);
5950 hr = d3dx_parse_effect_annotation(effect, &technique->annotations[i], data, ptr, objects);
5951 if (hr != D3D_OK)
5953 WARN("Failed to parse annotation %u\n", i);
5954 goto err_out;
5959 if (technique->pass_count)
5961 technique->passes = calloc(technique->pass_count, sizeof(*technique->passes));
5962 if (!technique->passes)
5964 ERR("Out of memory\n");
5965 hr = E_OUTOFMEMORY;
5966 goto err_out;
5969 for (i = 0; i < technique->pass_count; ++i)
5971 hr = d3dx_parse_effect_pass(effect, &technique->passes[i], data, ptr, objects);
5972 if (hr != D3D_OK)
5974 WARN("Failed to parse pass %u\n", i);
5975 goto err_out;
5980 technique->name = name;
5982 return D3D_OK;
5984 err_out:
5986 if (technique->passes)
5988 for (i = 0; i < technique->pass_count; ++i)
5989 free_pass(&technique->passes[i]);
5990 free(technique->passes);
5991 technique->passes = NULL;
5994 if (technique->annotations)
5996 for (i = 0; i < technique->annotation_count; ++i)
5997 free_parameter(&technique->annotations[i], FALSE, FALSE);
5998 free(technique->annotations);
5999 technique->annotations = NULL;
6002 free(name);
6004 return hr;
6007 static HRESULT d3dx9_create_object(struct d3dx_effect *effect, struct d3dx_object *object)
6009 struct d3dx_parameter *param = object->param;
6010 IDirect3DDevice9 *device = effect->device;
6011 HRESULT hr;
6013 if (*(char **)param->data)
6014 ERR("Parameter data already allocated.\n");
6016 switch (param->type)
6018 case D3DXPT_STRING:
6019 *(char **)param->data = malloc(object->size);
6020 if (!*(char **)param->data)
6022 ERR("Out of memory.\n");
6023 return E_OUTOFMEMORY;
6025 memcpy(*(char **)param->data, object->data, object->size);
6026 break;
6027 case D3DXPT_VERTEXSHADER:
6028 if (FAILED(hr = IDirect3DDevice9_CreateVertexShader(device, object->data,
6029 (IDirect3DVertexShader9 **)param->data)))
6031 WARN("Failed to create vertex shader.\n");
6032 object->creation_failed = TRUE;
6034 break;
6035 case D3DXPT_PIXELSHADER:
6036 if (FAILED(hr = IDirect3DDevice9_CreatePixelShader(device, object->data,
6037 (IDirect3DPixelShader9 **)param->data)))
6039 WARN("Failed to create pixel shader.\n");
6040 object->creation_failed = TRUE;
6042 break;
6043 default:
6044 break;
6046 return D3D_OK;
6049 static HRESULT d3dx_parse_array_selector(struct d3dx_effect *effect, struct d3dx_state *state,
6050 const char **skip_constants, unsigned int skip_constants_count)
6052 struct d3dx_parameter *param = &state->parameter;
6053 struct d3dx_object *object = &effect->objects[param->object_id];
6054 char *ptr = object->data;
6055 uint32_t string_size;
6056 HRESULT ret;
6058 TRACE("Parsing array entry selection state for parameter %p.\n", param);
6060 string_size = *(uint32_t *)ptr;
6061 state->referenced_param = get_parameter_by_name(&effect->params, NULL, ptr + 4);
6062 if (state->referenced_param)
6064 TRACE("Mapping to parameter %s.\n", debugstr_a(state->referenced_param->name));
6066 else
6068 FIXME("Referenced parameter %s not found.\n", ptr + 4);
6069 return D3DXERR_INVALIDDATA;
6071 TRACE("Unknown u32: 0x%.8x.\n", *(uint32_t *)(ptr + string_size));
6073 if (string_size % sizeof(uint32_t))
6074 FIXME("Unaligned string_size %u.\n", string_size);
6075 if (FAILED(ret = d3dx_create_param_eval(&effect->params, (uint32_t *)(ptr + string_size) + 1,
6076 object->size - (string_size + sizeof(uint32_t)), D3DXPT_INT, &param->param_eval,
6077 get_version_counter_ptr(effect), NULL, 0)))
6078 return ret;
6079 ret = D3D_OK;
6080 param = state->referenced_param;
6081 if (param->type == D3DXPT_VERTEXSHADER || param->type == D3DXPT_PIXELSHADER)
6083 unsigned int i;
6085 for (i = 0; i < param->element_count; i++)
6087 if (param->members[i].type != param->type)
6089 FIXME("Unexpected member parameter type %u, expected %u.\n", param->members[i].type, param->type);
6090 return D3DXERR_INVALIDDATA;
6092 if (!param->members[i].param_eval)
6094 TRACE("Creating preshader for object %u.\n", param->members[i].object_id);
6095 object = &effect->objects[param->members[i].object_id];
6096 if (FAILED(ret = d3dx_create_param_eval(&effect->params, object->data, object->size, param->type,
6097 &param->members[i].param_eval, get_version_counter_ptr(effect),
6098 skip_constants, skip_constants_count)))
6099 break;
6103 return ret;
6106 static HRESULT d3dx_parse_resource(struct d3dx_effect *effect, const char *data, const char **ptr,
6107 const char **skip_constants, unsigned int skip_constants_count)
6109 unsigned int index, state_index, usage, element_index, technique_index;
6110 struct d3dx_parameter *param;
6111 struct d3dx_object *object;
6112 struct d3dx_state *state;
6113 HRESULT hr = E_FAIL;
6115 technique_index = read_u32(ptr);
6116 TRACE("technique_index: %u.\n", technique_index);
6118 index = read_u32(ptr);
6119 TRACE("index: %u.\n", index);
6121 element_index = read_u32(ptr);
6122 TRACE("element_index: %u.\n", element_index);
6124 state_index = read_u32(ptr);
6125 TRACE("state_index: %u.\n", state_index);
6127 usage = read_u32(ptr);
6128 TRACE("usage: %u.\n", usage);
6130 if (technique_index == 0xffffffff)
6132 struct d3dx_parameter *parameter;
6133 struct d3dx_sampler *sampler;
6135 if (index >= effect->params.count)
6137 FIXME("Index out of bounds: index %u >= parameter count %u.\n", index, effect->params.count);
6138 return E_FAIL;
6141 parameter = &effect->params.parameters[index].param;
6142 if (element_index != 0xffffffff)
6144 if (element_index >= parameter->element_count && parameter->element_count != 0)
6146 FIXME("Index out of bounds: element_index %u >= element_count %u.\n", element_index, parameter->element_count);
6147 return E_FAIL;
6150 if (parameter->element_count)
6151 parameter = &parameter->members[element_index];
6154 sampler = parameter->data;
6155 if (state_index >= sampler->state_count)
6157 FIXME("Index out of bounds: state_index %u >= state_count %u.\n", state_index, sampler->state_count);
6158 return E_FAIL;
6161 state = &sampler->states[state_index];
6163 else
6165 struct d3dx_technique *technique;
6166 struct d3dx_pass *pass;
6168 if (technique_index >= effect->technique_count)
6170 FIXME("Index out of bounds: technique_index %u >= technique_count %u.\n", technique_index,
6171 effect->technique_count);
6172 return E_FAIL;
6175 technique = &effect->techniques[technique_index];
6176 if (index >= technique->pass_count)
6178 FIXME("Index out of bounds: index %u >= pass_count %u.\n", index, technique->pass_count);
6179 return E_FAIL;
6182 pass = &technique->passes[index];
6183 if (state_index >= pass->state_count)
6185 FIXME("Index out of bounds: state_index %u >= state_count %u.\n", state_index, pass->state_count);
6186 return E_FAIL;
6189 state = &pass->states[state_index];
6192 TRACE("State operation %#x (%s).\n", state->operation, state_table[state->operation].name);
6193 param = &state->parameter;
6194 TRACE("Using object id %u.\n", param->object_id);
6195 object = &effect->objects[param->object_id];
6197 TRACE("Usage %u: class %s, type %s.\n", usage, debug_d3dxparameter_class(param->class),
6198 debug_d3dxparameter_type(param->type));
6199 switch (usage)
6201 case 0:
6202 switch (param->type)
6204 case D3DXPT_VERTEXSHADER:
6205 case D3DXPT_PIXELSHADER:
6206 state->type = ST_CONSTANT;
6207 if (FAILED(hr = d3dx9_copy_data(effect, param->object_id, ptr)))
6208 return hr;
6210 if (object->data)
6212 if (FAILED(hr = d3dx9_create_object(effect, object)))
6213 return hr;
6214 if (FAILED(hr = d3dx_create_param_eval(&effect->params, object->data, object->size, param->type,
6215 &param->param_eval, get_version_counter_ptr(effect),
6216 skip_constants, skip_constants_count)))
6217 return hr;
6219 break;
6221 case D3DXPT_BOOL:
6222 case D3DXPT_INT:
6223 case D3DXPT_FLOAT:
6224 case D3DXPT_STRING:
6225 state->type = ST_FXLC;
6226 if (FAILED(hr = d3dx9_copy_data(effect, param->object_id, ptr)))
6227 return hr;
6228 if (FAILED(hr = d3dx_create_param_eval(&effect->params, object->data, object->size, param->type,
6229 &param->param_eval, get_version_counter_ptr(effect), NULL, 0)))
6230 return hr;
6231 break;
6233 default:
6234 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(param->type));
6235 break;
6237 break;
6239 case 1:
6240 state->type = ST_PARAMETER;
6241 if (FAILED(hr = d3dx9_copy_data(effect, param->object_id, ptr)))
6242 return hr;
6244 TRACE("Looking for parameter %s.\n", debugstr_a(object->data));
6245 state->referenced_param = get_parameter_by_name(&effect->params, NULL, object->data);
6246 if (state->referenced_param)
6248 struct d3dx_parameter *refpar = state->referenced_param;
6250 TRACE("Mapping to parameter %p, having object id %u.\n", refpar, refpar->object_id);
6251 if (refpar->type == D3DXPT_VERTEXSHADER || refpar->type == D3DXPT_PIXELSHADER)
6253 struct d3dx_object *refobj = &effect->objects[refpar->object_id];
6255 if (!refpar->param_eval)
6257 if (FAILED(hr = d3dx_create_param_eval(&effect->params, refobj->data, refobj->size,
6258 refpar->type, &refpar->param_eval, get_version_counter_ptr(effect),
6259 skip_constants, skip_constants_count)))
6260 return hr;
6264 else
6266 FIXME("Referenced parameter %s not found.\n", (char *)object->data);
6267 return D3DXERR_INVALIDDATA;
6269 break;
6271 case 2:
6272 state->type = ST_ARRAY_SELECTOR;
6273 if (FAILED(hr = d3dx9_copy_data(effect, param->object_id, ptr)))
6274 return hr;
6275 hr = d3dx_parse_array_selector(effect, state, skip_constants, skip_constants_count);
6276 break;
6278 default:
6279 FIXME("Unknown usage %u.\n", usage);
6280 break;
6283 return hr;
6286 static BOOL param_set_top_level_param(void *top_level_param, struct d3dx_parameter *param)
6288 param->top_level_param = top_level_param;
6289 return FALSE;
6292 static HRESULT d3dx_parse_effect(struct d3dx_effect *effect, const char *data, UINT data_size,
6293 uint32_t start, const char **skip_constants, unsigned int skip_constants_count)
6295 unsigned int string_count, resource_count, params_count;
6296 const char *ptr = data + start;
6297 unsigned int i;
6298 HRESULT hr;
6300 params_count = read_u32(&ptr);
6301 TRACE("Parameter count: %u.\n", params_count);
6303 effect->technique_count = read_u32(&ptr);
6304 TRACE("Technique count: %u.\n", effect->technique_count);
6306 skip_u32_unknown(&ptr, 1);
6308 effect->object_count = read_u32(&ptr);
6309 TRACE("Object count: %u.\n", effect->object_count);
6311 effect->objects = calloc(effect->object_count, sizeof(*effect->objects));
6312 if (!effect->objects)
6314 ERR("Out of memory.\n");
6315 hr = E_OUTOFMEMORY;
6316 goto err_out;
6319 if (FAILED(hr = d3dx_init_parameters_store(&effect->params, params_count)))
6321 hr = E_OUTOFMEMORY;
6322 goto err_out;
6325 for (i = 0; i < effect->params.count; ++i)
6327 param_set_magic_number(&effect->params.parameters[i].param);
6328 hr = d3dx_parse_effect_parameter(effect, &effect->params.parameters[i], data, &ptr, effect->objects);
6329 if (hr != D3D_OK)
6331 WARN("Failed to parse parameter %u.\n", i);
6332 goto err_out;
6334 walk_parameter_tree(&effect->params.parameters[i].param, param_set_top_level_param, &effect->params.parameters[i]);
6335 add_param_to_tree(effect, &effect->params.parameters[i].param, NULL, 0, 0);
6338 if (effect->technique_count)
6340 effect->techniques = calloc(effect->technique_count, sizeof(*effect->techniques));
6341 if (!effect->techniques)
6343 ERR("Out of memory.\n");
6344 hr = E_OUTOFMEMORY;
6345 goto err_out;
6348 for (i = 0; i < effect->technique_count; ++i)
6350 TRACE("Parsing technique %u.\n", i);
6351 hr = d3dx_parse_effect_technique(effect, &effect->techniques[i], data, &ptr, effect->objects);
6352 if (hr != D3D_OK)
6354 WARN("Failed to parse technique %u.\n", i);
6355 goto err_out;
6360 string_count = read_u32(&ptr);
6361 TRACE("String count: %u.\n", string_count);
6363 resource_count = read_u32(&ptr);
6364 TRACE("Resource count: %u.\n", resource_count);
6366 for (i = 0; i < string_count; ++i)
6368 unsigned int id;
6370 id = read_u32(&ptr);
6371 TRACE("id: %u.\n", id);
6373 if (FAILED(hr = d3dx9_copy_data(effect, id, &ptr)))
6374 goto err_out;
6376 if (effect->objects[id].data)
6378 if (FAILED(hr = d3dx9_create_object(effect, &effect->objects[id])))
6379 goto err_out;
6383 for (i = 0; i < resource_count; ++i)
6385 TRACE("parse resource %u.\n", i);
6387 hr = d3dx_parse_resource(effect, data, &ptr, skip_constants, skip_constants_count);
6388 if (hr != D3D_OK)
6390 WARN("Failed to parse resource %u.\n", i);
6391 goto err_out;
6395 for (i = 0; i < effect->params.count; ++i)
6397 if (FAILED(hr = d3dx_pool_sync_shared_parameter(effect->pool, &effect->params.parameters[i])))
6398 goto err_out;
6399 effect->params.parameters[i].version_counter = get_version_counter_ptr(effect);
6400 set_dirty(&effect->params.parameters[i].param);
6402 return D3D_OK;
6404 err_out:
6406 if (effect->techniques)
6408 for (i = 0; i < effect->technique_count; ++i)
6409 free_technique(&effect->techniques[i]);
6410 free(effect->techniques);
6411 effect->techniques = NULL;
6414 d3dx_parameters_store_cleanup(&effect->params);
6416 if (effect->objects)
6418 for (i = 0; i < effect->object_count; ++i)
6420 free_object(&effect->objects[i]);
6422 free(effect->objects);
6423 effect->objects = NULL;
6426 return hr;
6429 #define INITIAL_CONST_NAMES_SIZE 4
6431 static char *next_valid_constant_name(char **string)
6433 char *ret = *string;
6434 char *next;
6436 while (*ret && !isalpha(*ret) && *ret != '_')
6437 ++ret;
6438 if (!*ret)
6439 return NULL;
6441 next = ret + 1;
6442 while (isalpha(*next) || isdigit(*next) || *next == '_')
6443 ++next;
6444 if (*next)
6445 *next++ = 0;
6446 *string = next;
6447 return ret;
6450 static const char **parse_skip_constants_string(char *skip_constants_string, unsigned int *names_count)
6452 const char **names, **new_alloc;
6453 const char *name;
6454 char *s;
6455 unsigned int size = INITIAL_CONST_NAMES_SIZE;
6457 names = malloc(sizeof(*names) * size);
6458 if (!names)
6459 return NULL;
6461 *names_count = 0;
6462 s = skip_constants_string;
6463 while ((name = next_valid_constant_name(&s)))
6465 if (*names_count == size)
6467 size *= 2;
6468 new_alloc = realloc(names, sizeof(*names) * size);
6469 if (!new_alloc)
6471 free(names);
6472 return NULL;
6474 names = new_alloc;
6476 names[(*names_count)++] = name;
6478 new_alloc = realloc(names, *names_count * sizeof(*names));
6479 if (!new_alloc)
6480 return names;
6481 return new_alloc;
6484 static HRESULT d3dx9_effect_init_from_binary(struct d3dx_effect *effect,
6485 struct IDirect3DDevice9 *device, const char *data, SIZE_T data_size,
6486 unsigned int flags, struct ID3DXEffectPool *pool, const char *skip_constants_string)
6488 unsigned int skip_constants_count = 0;
6489 char *skip_constants_buffer = NULL;
6490 const char **skip_constants = NULL;
6491 const char *ptr = data;
6492 uint32_t tag, offset;
6493 unsigned int i, j;
6494 HRESULT hr;
6496 effect->ID3DXEffect_iface.lpVtbl = &ID3DXEffect_Vtbl;
6497 effect->ref = 1;
6499 effect->flags = flags;
6501 list_init(&effect->parameter_block_list);
6503 tag = read_u32(&ptr);
6504 TRACE("Tag: %#x.\n", tag);
6506 if (!(flags & D3DXFX_NOT_CLONEABLE))
6508 if (!(effect->source = malloc(data_size)))
6509 return E_OUTOFMEMORY;
6510 memcpy(effect->source, data, data_size);
6511 effect->source_size = data_size;
6514 if (pool)
6516 effect->pool = unsafe_impl_from_ID3DXEffectPool(pool);
6517 pool->lpVtbl->AddRef(pool);
6520 IDirect3DDevice9_AddRef(device);
6521 effect->device = device;
6523 if (skip_constants_string)
6525 if (!(flags & D3DXFX_NOT_CLONEABLE) && !(effect->skip_constants_string = strdup(skip_constants_string)))
6527 hr = E_OUTOFMEMORY;
6528 goto fail;
6531 if (!(skip_constants_buffer = strdup(skip_constants_string)))
6533 hr = E_OUTOFMEMORY;
6534 goto fail;
6537 if (!(skip_constants = parse_skip_constants_string(skip_constants_buffer, &skip_constants_count)))
6539 free(skip_constants_buffer);
6540 hr = E_OUTOFMEMORY;
6541 goto fail;
6544 offset = read_u32(&ptr);
6545 TRACE("Offset: %#x.\n", offset);
6547 hr = d3dx_parse_effect(effect, ptr, data_size, offset, skip_constants, skip_constants_count);
6548 if (hr != D3D_OK)
6550 FIXME("Failed to parse effect.\n");
6551 free(skip_constants_buffer);
6552 free(skip_constants);
6553 goto fail;
6556 for (i = 0; i < skip_constants_count; ++i)
6558 struct d3dx_parameter *param;
6559 param = get_parameter_by_name(&effect->params, NULL, skip_constants[i]);
6560 if (param)
6562 for (j = 0; j < effect->technique_count; ++j)
6564 if (is_parameter_used(param, &effect->techniques[j]))
6566 WARN("skip_constants parameter %s is used in technique %u.\n",
6567 debugstr_a(skip_constants[i]), j);
6568 free(skip_constants_buffer);
6569 free(skip_constants);
6570 hr = D3DERR_INVALIDCALL;
6571 goto fail;
6575 else
6577 TRACE("skip_constants parameter %s not found.\n",
6578 debugstr_a(skip_constants[i]));
6582 free(skip_constants_buffer);
6583 free(skip_constants);
6585 /* initialize defaults - check because of unsupported ascii effects */
6586 if (effect->techniques)
6588 effect->active_technique = &effect->techniques[0];
6589 effect->active_pass = NULL;
6592 return D3D_OK;
6594 fail:
6595 if (effect->techniques)
6597 for (i = 0; i < effect->technique_count; ++i)
6598 free_technique(&effect->techniques[i]);
6599 free(effect->techniques);
6602 if (effect->params.parameters)
6604 for (i = 0; i < effect->params.count; ++i)
6605 free_top_level_parameter(&effect->params.parameters[i]);
6606 free(effect->params.parameters);
6609 if (effect->objects)
6611 for (i = 0; i < effect->object_count; ++i)
6612 free_object(&effect->objects[i]);
6613 free(effect->objects);
6616 IDirect3DDevice9_Release(effect->device);
6617 if (pool)
6618 pool->lpVtbl->Release(pool);
6619 free(effect->source);
6620 free(effect->skip_constants_string);
6621 return hr;
6624 static HRESULT d3dx9_effect_init(struct d3dx_effect *effect, struct IDirect3DDevice9 *device,
6625 const char *data, SIZE_T data_size, const D3D_SHADER_MACRO *defines, ID3DInclude *include,
6626 UINT flags, ID3DBlob **errors, struct ID3DXEffectPool *pool, const char *skip_constants_string)
6628 #if D3DX_SDK_VERSION <= 36
6629 UINT compile_flags = D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY;
6630 #else
6631 UINT compile_flags = 0;
6632 #endif
6633 ID3DBlob *bytecode = NULL, *temp_errors = NULL;
6634 const char *ptr = data;
6635 unsigned int tag;
6636 HRESULT hr;
6638 TRACE("effect %p, device %p, data %p, data_size %Iu, defines %p, include %p, flags %#x, errors %p, "
6639 "pool %p, skip_constants %s.\n",
6640 effect, device, data, data_size, defines, include, flags, errors, pool,
6641 debugstr_a(skip_constants_string));
6643 tag = read_u32(&ptr);
6645 if (tag == d3dx9_effect_version(9, 1))
6646 return d3dx9_effect_init_from_binary(effect, device, data, data_size, flags, pool, skip_constants_string);
6648 TRACE("HLSL ASCII effect, trying to compile it.\n");
6649 compile_flags |= flags & ~(D3DXFX_NOT_CLONEABLE | D3DXFX_LARGEADDRESSAWARE);
6650 hr = D3DCompile(data, data_size, NULL, defines, include,
6651 NULL, "fx_2_0", compile_flags, 0, &bytecode, &temp_errors);
6652 if (FAILED(hr))
6654 WARN("Failed to compile ASCII effect.\n");
6655 if (bytecode)
6656 ID3D10Blob_Release(bytecode);
6657 if (temp_errors)
6659 const char *error_string = ID3D10Blob_GetBufferPointer(temp_errors);
6660 const char *string_ptr;
6662 while (*error_string)
6664 string_ptr = error_string;
6665 while (*string_ptr && *string_ptr != '\n' && *string_ptr != '\r'
6666 && string_ptr - error_string < 80)
6667 ++string_ptr;
6668 TRACE("%s\n", debugstr_an(error_string, string_ptr - error_string));
6669 error_string = string_ptr;
6670 while (*error_string == '\n' || *error_string == '\r')
6671 ++error_string;
6674 if (errors)
6675 *errors = temp_errors;
6676 else if (temp_errors)
6677 ID3D10Blob_Release(temp_errors);
6678 return hr;
6680 if (!bytecode)
6682 FIXME("No output from effect compilation.\n");
6683 return D3DERR_INVALIDCALL;
6685 if (errors)
6686 *errors = temp_errors;
6687 else if (temp_errors)
6688 ID3D10Blob_Release(temp_errors);
6690 hr = d3dx9_effect_init_from_binary(effect, device, ID3D10Blob_GetBufferPointer(bytecode),
6691 ID3D10Blob_GetBufferSize(bytecode), flags, pool, skip_constants_string);
6692 ID3D10Blob_Release(bytecode);
6693 return hr;
6696 HRESULT WINAPI D3DXCreateEffectEx(struct IDirect3DDevice9 *device, const void *srcdata, UINT srcdatalen,
6697 const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skip_constants, DWORD flags,
6698 struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilation_errors)
6700 struct d3dx_effect *object;
6701 HRESULT hr;
6703 TRACE("device %p, srcdata %p, srcdatalen %u, defines %p, include %p, "
6704 "skip_constants %p, flags %#lx, pool %p, effect %p, compilation_errors %p.\n",
6705 device, srcdata, srcdatalen, defines, include,
6706 skip_constants, flags, pool, effect, compilation_errors);
6708 if (compilation_errors)
6709 *compilation_errors = NULL;
6711 if (!device || !srcdata)
6712 return D3DERR_INVALIDCALL;
6714 if (!srcdatalen)
6715 return E_FAIL;
6717 /* Native dll allows effect to be null so just return D3D_OK after doing basic checks */
6718 if (!effect)
6719 return D3D_OK;
6721 object = calloc(1, sizeof(*object));
6722 if (!object)
6723 return E_OUTOFMEMORY;
6725 hr = d3dx9_effect_init(object, device, srcdata, srcdatalen, (const D3D_SHADER_MACRO *)defines,
6726 (ID3DInclude *)include, flags, (ID3DBlob **)compilation_errors, pool, skip_constants);
6727 if (FAILED(hr))
6729 WARN("Failed to create effect object, hr %#lx.\n", hr);
6730 return hr;
6733 *effect = &object->ID3DXEffect_iface;
6735 TRACE("Created ID3DXEffect %p\n", object);
6737 return D3D_OK;
6740 HRESULT WINAPI D3DXCreateEffect(struct IDirect3DDevice9 *device, const void *data, UINT data_size,
6741 const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags,
6742 struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
6744 TRACE("device %p, data %p, data_size %u, defines %p, include %p, flags %#lx, pool %p, "
6745 "effect %p, messages %p.\n", device, data, data_size, defines,
6746 include, flags, pool, effect, messages);
6748 return D3DXCreateEffectEx(device, data, data_size, defines, include, NULL, flags, pool, effect, messages);
6751 static HRESULT d3dx9_effect_compiler_init(struct ID3DXEffectCompilerImpl *compiler,
6752 const char *data, SIZE_T data_size, const D3D_SHADER_MACRO *defines, ID3DInclude *include,
6753 UINT eflags, ID3DBlob **messages)
6755 TRACE("compiler %p, data %p, data_size %Iu, defines %p, include %p, eflags %#x, messages %p.\n",
6756 compiler, data, data_size, defines, include, eflags, messages);
6758 compiler->ID3DXEffectCompiler_iface.lpVtbl = &ID3DXEffectCompiler_Vtbl;
6759 compiler->ref = 1;
6761 FIXME("ID3DXEffectCompiler implementation is only a stub.\n");
6763 return D3D_OK;
6766 HRESULT WINAPI D3DXCreateEffectCompiler(const char *data, UINT data_size, const D3DXMACRO *defines,
6767 ID3DXInclude *include, DWORD flags, ID3DXEffectCompiler **compiler, ID3DXBuffer **messages)
6769 struct ID3DXEffectCompilerImpl *object;
6770 HRESULT hr;
6772 TRACE("data %p, data_size %u, defines %p, include %p, flags %#lx, compiler %p, messages %p.\n",
6773 data, data_size, defines, include, flags, compiler, messages);
6775 if (!data || !compiler)
6777 WARN("Invalid arguments supplied\n");
6778 return D3DERR_INVALIDCALL;
6781 object = calloc(1, sizeof(*object));
6782 if (!object)
6783 return E_OUTOFMEMORY;
6785 hr = d3dx9_effect_compiler_init(object, data, data_size, (const D3D_SHADER_MACRO *)defines,
6786 (ID3DInclude *)include, flags, (ID3DBlob **)messages);
6787 if (FAILED(hr))
6789 WARN("Failed to initialize effect compiler\n");
6790 free(object);
6791 return hr;
6794 *compiler = &object->ID3DXEffectCompiler_iface;
6796 TRACE("Created ID3DXEffectCompiler %p\n", object);
6798 return D3D_OK;
6801 /*** IUnknown methods ***/
6802 static HRESULT WINAPI d3dx_effect_pool_QueryInterface(ID3DXEffectPool *iface, REFIID riid, void **object)
6804 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
6806 if (IsEqualGUID(riid, &IID_IUnknown) ||
6807 IsEqualGUID(riid, &IID_ID3DXEffectPool))
6809 iface->lpVtbl->AddRef(iface);
6810 *object = iface;
6811 return S_OK;
6814 WARN("Interface %s not found\n", debugstr_guid(riid));
6816 return E_NOINTERFACE;
6819 static ULONG WINAPI d3dx_effect_pool_AddRef(ID3DXEffectPool *iface)
6821 struct d3dx_effect_pool *pool = impl_from_ID3DXEffectPool(iface);
6822 ULONG refcount = InterlockedIncrement(&pool->refcount);
6824 TRACE("%p increasing refcount to %lu.\n", pool, refcount);
6826 return refcount;
6829 static void free_effect_pool(struct d3dx_effect_pool *pool)
6831 unsigned int i;
6833 for (i = 0; i < pool->size; ++i)
6835 if (pool->shared_data[i].count)
6837 unsigned int j;
6839 WARN("Releasing pool with referenced parameters.\n");
6841 param_set_data_pointer(&pool->shared_data[i].parameters[0]->param, NULL, FALSE, TRUE);
6842 pool->shared_data[i].parameters[0]->shared_data = NULL;
6844 for (j = 1; j < pool->shared_data[i].count; ++j)
6846 walk_parameter_tree(&pool->shared_data[i].parameters[j]->param, param_zero_data_func, NULL);
6847 pool->shared_data[i].parameters[j]->shared_data = NULL;
6849 free(pool->shared_data[i].parameters);
6852 free(pool->shared_data);
6853 free(pool);
6856 static ULONG WINAPI d3dx_effect_pool_Release(ID3DXEffectPool *iface)
6858 struct d3dx_effect_pool *pool = impl_from_ID3DXEffectPool(iface);
6859 ULONG refcount = InterlockedDecrement(&pool->refcount);
6861 TRACE("%p decreasing refcount to %lu.\n", pool, refcount);
6863 if (!refcount)
6864 free_effect_pool(pool);
6866 return refcount;
6869 static const struct ID3DXEffectPoolVtbl ID3DXEffectPool_Vtbl =
6871 /*** IUnknown methods ***/
6872 d3dx_effect_pool_QueryInterface,
6873 d3dx_effect_pool_AddRef,
6874 d3dx_effect_pool_Release
6877 static inline struct d3dx_effect_pool *unsafe_impl_from_ID3DXEffectPool(ID3DXEffectPool *iface)
6879 if (!iface)
6880 return NULL;
6882 assert(iface->lpVtbl == &ID3DXEffectPool_Vtbl);
6883 return impl_from_ID3DXEffectPool(iface);
6886 HRESULT WINAPI D3DXCreateEffectPool(ID3DXEffectPool **pool)
6888 struct d3dx_effect_pool *object;
6890 TRACE("pool %p.\n", pool);
6892 if (!pool)
6893 return D3DERR_INVALIDCALL;
6895 object = calloc(1, sizeof(*object));
6896 if (!object)
6897 return E_OUTOFMEMORY;
6899 object->ID3DXEffectPool_iface.lpVtbl = &ID3DXEffectPool_Vtbl;
6900 object->refcount = 1;
6902 *pool = &object->ID3DXEffectPool_iface;
6904 return S_OK;
6907 HRESULT WINAPI D3DXCreateEffectFromFileExW(struct IDirect3DDevice9 *device, const WCHAR *srcfile,
6908 const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skipconstants, DWORD flags,
6909 struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
6911 struct d3dx_include_from_file include_from_file;
6912 const void *buffer;
6913 unsigned int size;
6914 char *filename_a;
6915 HRESULT ret;
6917 TRACE("device %p, srcfile %s, defines %p, include %p, skipconstants %s, "
6918 "flags %#lx, pool %p, effect %p, messages %p.\n",
6919 device, debugstr_w(srcfile), defines, include, debugstr_a(skipconstants),
6920 flags, pool, effect, messages);
6922 if (!device || !srcfile)
6923 return D3DERR_INVALIDCALL;
6925 if (!include)
6927 include_from_file.ID3DXInclude_iface.lpVtbl = &d3dx_include_from_file_vtbl;
6928 include = &include_from_file.ID3DXInclude_iface;
6931 size = WideCharToMultiByte(CP_ACP, 0, srcfile, -1, NULL, 0, NULL, NULL);
6932 filename_a = malloc(size);
6933 if (!filename_a)
6934 return E_OUTOFMEMORY;
6935 WideCharToMultiByte(CP_ACP, 0, srcfile, -1, filename_a, size, NULL, NULL);
6937 EnterCriticalSection(&from_file_mutex);
6938 ret = ID3DXInclude_Open(include, D3DXINC_LOCAL, filename_a, NULL, &buffer, &size);
6939 if (FAILED(ret))
6941 LeaveCriticalSection(&from_file_mutex);
6942 free(filename_a);
6943 return D3DXERR_INVALIDDATA;
6946 ret = D3DXCreateEffectEx(device, buffer, size, defines, include, skipconstants, flags, pool,
6947 effect, messages);
6949 ID3DXInclude_Close(include, buffer);
6950 LeaveCriticalSection(&from_file_mutex);
6951 free(filename_a);
6952 return ret;
6955 HRESULT WINAPI D3DXCreateEffectFromFileExA(struct IDirect3DDevice9 *device, const char *srcfile,
6956 const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skipconstants, DWORD flags,
6957 struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
6959 WCHAR *srcfileW;
6960 HRESULT ret;
6961 DWORD len;
6963 TRACE("device %p, srcfile %s, defines %p, include %p, skipconstants %s, "
6964 "flags %#lx, pool %p, effect %p, messages %p.\n",
6965 device, debugstr_a(srcfile), defines, include, debugstr_a(skipconstants),
6966 flags, pool, effect, messages);
6968 if (!srcfile)
6969 return D3DERR_INVALIDCALL;
6971 len = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0);
6972 srcfileW = malloc(len * sizeof(*srcfileW));
6973 MultiByteToWideChar(CP_ACP, 0, srcfile, -1, srcfileW, len);
6975 ret = D3DXCreateEffectFromFileExW(device, srcfileW, defines, include, skipconstants, flags, pool, effect, messages);
6976 free(srcfileW);
6978 return ret;
6981 HRESULT WINAPI D3DXCreateEffectFromFileW(struct IDirect3DDevice9 *device, const WCHAR *srcfile,
6982 const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags, struct ID3DXEffectPool *pool,
6983 struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
6985 TRACE("(void): relay\n");
6986 return D3DXCreateEffectFromFileExW(device, srcfile, defines, include, NULL, flags, pool,
6987 effect, messages);
6990 HRESULT WINAPI D3DXCreateEffectFromFileA(struct IDirect3DDevice9 *device, const char *srcfile,
6991 const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags, struct ID3DXEffectPool *pool,
6992 struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
6994 TRACE("(void): relay\n");
6995 return D3DXCreateEffectFromFileExA(device, srcfile, defines, include, NULL, flags, pool,
6996 effect, messages);
6999 HRESULT WINAPI D3DXCreateEffectFromResourceExW(struct IDirect3DDevice9 *device, HMODULE srcmodule,
7000 const WCHAR *srcresource, const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skipconstants,
7001 DWORD flags, struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
7003 HRSRC resinfo;
7004 void *buffer;
7005 DWORD size;
7007 TRACE("device %p, srcmodule %p, srcresource %s, defines %p, include %p, skipconstants %s, "
7008 "flags %#lx, pool %p, effect %p, messages %p.\n",
7009 device, srcmodule, debugstr_w(srcresource), defines, include, debugstr_a(skipconstants),
7010 flags, pool, effect, messages);
7012 if (!device)
7013 return D3DERR_INVALIDCALL;
7015 if (!(resinfo = FindResourceW(srcmodule, srcresource, (const WCHAR *)RT_RCDATA)))
7016 return D3DXERR_INVALIDDATA;
7018 if (FAILED(load_resource_into_memory(srcmodule, resinfo, &buffer, &size)))
7019 return D3DXERR_INVALIDDATA;
7021 return D3DXCreateEffectEx(device, buffer, size, defines, include,
7022 skipconstants, flags, pool, effect, messages);
7025 HRESULT WINAPI D3DXCreateEffectFromResourceExA(struct IDirect3DDevice9 *device, HMODULE srcmodule,
7026 const char *srcresource, const D3DXMACRO *defines, struct ID3DXInclude *include,
7027 const char *skipconstants, DWORD flags, struct ID3DXEffectPool *pool,
7028 struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
7030 HRSRC resinfo;
7031 void *buffer;
7032 DWORD size;
7034 TRACE("device %p, srcmodule %p, srcresource %s, defines %p, include %p, skipconstants %s, "
7035 "flags %#lx, pool %p, effect %p, messages %p.\n",
7036 device, srcmodule, debugstr_a(srcresource), defines, include, debugstr_a(skipconstants),
7037 flags, pool, effect, messages);
7039 if (!device)
7040 return D3DERR_INVALIDCALL;
7042 if (!(resinfo = FindResourceA(srcmodule, srcresource, (const char *)RT_RCDATA)))
7043 return D3DXERR_INVALIDDATA;
7045 if (FAILED(load_resource_into_memory(srcmodule, resinfo, &buffer, &size)))
7046 return D3DXERR_INVALIDDATA;
7048 return D3DXCreateEffectEx(device, buffer, size, defines, include,
7049 skipconstants, flags, pool, effect, messages);
7052 HRESULT WINAPI D3DXCreateEffectFromResourceW(struct IDirect3DDevice9 *device, HMODULE srcmodule,
7053 const WCHAR *srcresource, const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags,
7054 struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
7056 TRACE("(void): relay\n");
7057 return D3DXCreateEffectFromResourceExW(device, srcmodule, srcresource, defines, include, NULL,
7058 flags, pool, effect, messages);
7061 HRESULT WINAPI D3DXCreateEffectFromResourceA(struct IDirect3DDevice9 *device, HMODULE srcmodule,
7062 const char *srcresource, const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags,
7063 struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **messages)
7065 TRACE("(void): relay\n");
7066 return D3DXCreateEffectFromResourceExA(device, srcmodule, srcresource, defines, include, NULL,
7067 flags, pool, effect, messages);
7070 HRESULT WINAPI D3DXCreateEffectCompilerFromFileW(const WCHAR *srcfile, const D3DXMACRO *defines,
7071 ID3DXInclude *include, DWORD flags, ID3DXEffectCompiler **compiler, ID3DXBuffer **messages)
7073 void *buffer;
7074 HRESULT ret;
7075 DWORD size;
7077 TRACE("srcfile %s, defines %p, include %p, flags %#lx, compiler %p, messages %p.\n",
7078 debugstr_w(srcfile), defines, include, flags, compiler, messages);
7080 if (!srcfile)
7081 return D3DERR_INVALIDCALL;
7083 ret = map_view_of_file(srcfile, &buffer, &size);
7085 if (FAILED(ret))
7086 return D3DXERR_INVALIDDATA;
7088 ret = D3DXCreateEffectCompiler(buffer, size, defines, include, flags, compiler, messages);
7089 UnmapViewOfFile(buffer);
7091 return ret;
7094 HRESULT WINAPI D3DXCreateEffectCompilerFromFileA(const char *srcfile, const D3DXMACRO *defines,
7095 ID3DXInclude *include, DWORD flags, ID3DXEffectCompiler **compiler, ID3DXBuffer **messages)
7097 WCHAR *srcfileW;
7098 HRESULT ret;
7099 DWORD len;
7101 TRACE("srcfile %s, defines %p, include %p, flags %#lx, compiler %p, messages %p.\n",
7102 debugstr_a(srcfile), defines, include, flags, compiler, messages);
7104 if (!srcfile)
7105 return D3DERR_INVALIDCALL;
7107 len = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0);
7108 srcfileW = malloc(len * sizeof(*srcfileW));
7109 MultiByteToWideChar(CP_ACP, 0, srcfile, -1, srcfileW, len);
7111 ret = D3DXCreateEffectCompilerFromFileW(srcfileW, defines, include, flags, compiler, messages);
7112 free(srcfileW);
7114 return ret;
7117 HRESULT WINAPI D3DXCreateEffectCompilerFromResourceA(HMODULE srcmodule, const char *srcresource,
7118 const D3DXMACRO *defines, ID3DXInclude *include, DWORD flags,
7119 ID3DXEffectCompiler **compiler, ID3DXBuffer **messages)
7121 HRSRC resinfo;
7122 void *buffer;
7123 DWORD size;
7125 TRACE("srcmodule %p, srcresource %s, defines %p, include %p, flags %#lx, compiler %p, messages %p.\n",
7126 srcmodule, debugstr_a(srcresource), defines, include, flags, compiler, messages);
7128 if (!(resinfo = FindResourceA(srcmodule, srcresource, (const char *)RT_RCDATA)))
7129 return D3DXERR_INVALIDDATA;
7131 if (FAILED(load_resource_into_memory(srcmodule, resinfo, &buffer, &size)))
7132 return D3DXERR_INVALIDDATA;
7134 return D3DXCreateEffectCompiler(buffer, size, defines, include, flags, compiler, messages);
7137 HRESULT WINAPI D3DXCreateEffectCompilerFromResourceW(HMODULE srcmodule, const WCHAR *srcresource,
7138 const D3DXMACRO *defines, ID3DXInclude *include, DWORD flags,
7139 ID3DXEffectCompiler **compiler, ID3DXBuffer **messages)
7141 HRSRC resinfo;
7142 void *buffer;
7143 DWORD size;
7145 TRACE("srcmodule %p, srcresource %s, defines %p, include %p, flags %#lx, compiler %p, messages %p.\n",
7146 srcmodule, debugstr_w(srcresource), defines, include, flags, compiler, messages);
7148 if (!(resinfo = FindResourceW(srcmodule, srcresource, (const WCHAR *)RT_RCDATA)))
7149 return D3DXERR_INVALIDDATA;
7151 if (FAILED(load_resource_into_memory(srcmodule, resinfo, &buffer, &size)))
7152 return D3DXERR_INVALIDDATA;
7154 return D3DXCreateEffectCompiler(buffer, size, defines, include, flags, compiler, messages);
7157 HRESULT WINAPI D3DXDisassembleEffect(ID3DXEffect *effect, BOOL enable_color_code, ID3DXBuffer **disassembly)
7159 FIXME("(%p, %u, %p): stub\n", effect, enable_color_code, disassembly);
7161 return D3DXERR_INVALIDDATA;