ReactOS  0.4.15-dev-2355-gaf9df93
effect.c
Go to the documentation of this file.
1 #ifdef __REACTOS__
2 #include "precomp.h"
3 #else
4 /*
5  * Copyright 2010 Christian Costa
6  * Copyright 2011 Rico Schüller
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 
23 
24 #include <stdio.h>
25 #include <assert.h>
26 
27 #include "d3dx9_private.h"
28 #include "d3dcompiler.h"
29 #include "winternl.h"
30 #include "wine/list.h"
31 #endif /* __REACTOS__ */
32 
33 /* Constants for special INT/FLOAT conversation */
34 #define INT_FLOAT_MULTI 255.0f
35 #define INT_FLOAT_MULTI_INVERSE (1/INT_FLOAT_MULTI)
36 
37 static const char parameter_magic_string[4] = {'@', '!', '#', '\xFF'};
38 static const char parameter_block_magic_string[4] = {'@', '!', '#', '\xFE'};
39 
40 #define PARAMETER_FLAG_SHARED 1
41 
42 #define INITIAL_POOL_SIZE 16
43 #define INITIAL_PARAM_BLOCK_SIZE 1024
44 
46 
48 {
64 };
65 
67 {
73 };
74 
76 {
90 };
91 
93 {
100 };
101 
103 {
108 };
109 
111 {
113  void *data;
116 };
117 
119 {
125 };
126 
128 {
131 };
132 
133 struct d3dx_pass
134 {
135  char *name;
138 
141 
143 };
144 
146 {
147  char *name;
150 
152  struct d3dx_pass *passes;
153 
154  struct IDirect3DStateBlock9 *saved_state;
155 };
156 
158 {
161  struct list entry;
162  size_t size;
163  size_t offset;
165 };
166 
168 {
170  unsigned int bytes;
171 };
172 
174 {
175  ID3DXEffect ID3DXEffect_iface;
177 
178  unsigned int parameter_count;
179  unsigned int technique_count;
180  unsigned int object_count;
185 
188  unsigned int full_name_tmp_size;
189 
190  struct ID3DXEffectStateManager *manager;
191  struct IDirect3DDevice9 *device;
198 
200  unsigned int light_updated;
203 
206 };
207 
208 #define INITIAL_SHARED_DATA_SIZE 4
209 
211 {
212  ID3DXEffectPool ID3DXEffectPool_iface;
214 
216  unsigned int size;
217 
219 };
220 
222 {
223  ID3DXEffectCompiler ID3DXEffectCompiler_iface;
225 };
226 
227 static HRESULT d3dx_parse_state(struct d3dx_effect *effect, struct d3dx_state *state,
228  const char *data, const char **ptr, struct d3dx_object *objects);
229 static void free_parameter(struct d3dx_parameter *param, BOOL element, BOOL child);
230 
232 
233 static const struct
234 {
235  enum STATE_CLASS class;
237  const char *name;
238 }
239 state_table[] =
240 {
241  /* Render states */
242  {SC_RENDERSTATE, D3DRS_ZENABLE, "D3DRS_ZENABLE"}, /* 0x0 */
243  {SC_RENDERSTATE, D3DRS_FILLMODE, "D3DRS_FILLMODE"},
244  {SC_RENDERSTATE, D3DRS_SHADEMODE, "D3DRS_SHADEMODE"},
245  {SC_RENDERSTATE, D3DRS_ZWRITEENABLE, "D3DRS_ZWRITEENABLE"},
246  {SC_RENDERSTATE, D3DRS_ALPHATESTENABLE, "D3DRS_ALPHATESTENABLE"},
247  {SC_RENDERSTATE, D3DRS_LASTPIXEL, "D3DRS_LASTPIXEL"},
248  {SC_RENDERSTATE, D3DRS_SRCBLEND, "D3DRS_SRCBLEND"},
249  {SC_RENDERSTATE, D3DRS_DESTBLEND, "D3DRS_DESTBLEND"},
250  {SC_RENDERSTATE, D3DRS_CULLMODE, "D3DRS_CULLMODE"},
251  {SC_RENDERSTATE, D3DRS_ZFUNC, "D3DRS_ZFUNC"},
252  {SC_RENDERSTATE, D3DRS_ALPHAREF, "D3DRS_ALPHAREF"},
253  {SC_RENDERSTATE, D3DRS_ALPHAFUNC, "D3DRS_ALPHAFUNC"},
254  {SC_RENDERSTATE, D3DRS_DITHERENABLE, "D3DRS_DITHERENABLE"},
255  {SC_RENDERSTATE, D3DRS_ALPHABLENDENABLE, "D3DRS_ALPHABLENDENABLE"},
256  {SC_RENDERSTATE, D3DRS_FOGENABLE, "D3DRS_FOGENABLE"},
257  {SC_RENDERSTATE, D3DRS_SPECULARENABLE, "D3DRS_SPECULARENABLE"},
258  {SC_RENDERSTATE, D3DRS_FOGCOLOR, "D3DRS_FOGCOLOR"}, /* 0x10 */
259  {SC_RENDERSTATE, D3DRS_FOGTABLEMODE, "D3DRS_FOGTABLEMODE"},
260  {SC_RENDERSTATE, D3DRS_FOGSTART, "D3DRS_FOGSTART"},
261  {SC_RENDERSTATE, D3DRS_FOGEND, "D3DRS_FOGEND"},
262  {SC_RENDERSTATE, D3DRS_FOGDENSITY, "D3DRS_FOGDENSITY"},
263  {SC_RENDERSTATE, D3DRS_RANGEFOGENABLE, "D3DRS_RANGEFOGENABLE"},
264  {SC_RENDERSTATE, D3DRS_STENCILENABLE, "D3DRS_STENCILENABLE"},
265  {SC_RENDERSTATE, D3DRS_STENCILFAIL, "D3DRS_STENCILFAIL"},
266  {SC_RENDERSTATE, D3DRS_STENCILZFAIL, "D3DRS_STENCILZFAIL"},
267  {SC_RENDERSTATE, D3DRS_STENCILPASS, "D3DRS_STENCILPASS"},
268  {SC_RENDERSTATE, D3DRS_STENCILFUNC, "D3DRS_STENCILFUNC"},
269  {SC_RENDERSTATE, D3DRS_STENCILREF, "D3DRS_STENCILREF"},
270  {SC_RENDERSTATE, D3DRS_STENCILMASK, "D3DRS_STENCILMASK"},
271  {SC_RENDERSTATE, D3DRS_STENCILWRITEMASK, "D3DRS_STENCILWRITEMASK"},
272  {SC_RENDERSTATE, D3DRS_TEXTUREFACTOR, "D3DRS_TEXTUREFACTOR"},
273  {SC_RENDERSTATE, D3DRS_WRAP0, "D3DRS_WRAP0"},
274  {SC_RENDERSTATE, D3DRS_WRAP1, "D3DRS_WRAP1"}, /* 0x20 */
275  {SC_RENDERSTATE, D3DRS_WRAP2, "D3DRS_WRAP2"},
276  {SC_RENDERSTATE, D3DRS_WRAP3, "D3DRS_WRAP3"},
277  {SC_RENDERSTATE, D3DRS_WRAP4, "D3DRS_WRAP4"},
278  {SC_RENDERSTATE, D3DRS_WRAP5, "D3DRS_WRAP5"},
279  {SC_RENDERSTATE, D3DRS_WRAP6, "D3DRS_WRAP6"},
280  {SC_RENDERSTATE, D3DRS_WRAP7, "D3DRS_WRAP7"},
281  {SC_RENDERSTATE, D3DRS_WRAP8, "D3DRS_WRAP8"},
282  {SC_RENDERSTATE, D3DRS_WRAP9, "D3DRS_WRAP9"},
283  {SC_RENDERSTATE, D3DRS_WRAP10, "D3DRS_WRAP10"},
284  {SC_RENDERSTATE, D3DRS_WRAP11, "D3DRS_WRAP11"},
285  {SC_RENDERSTATE, D3DRS_WRAP12, "D3DRS_WRAP12"},
286  {SC_RENDERSTATE, D3DRS_WRAP13, "D3DRS_WRAP13"},
287  {SC_RENDERSTATE, D3DRS_WRAP14, "D3DRS_WRAP14"},
288  {SC_RENDERSTATE, D3DRS_WRAP15, "D3DRS_WRAP15"},
289  {SC_RENDERSTATE, D3DRS_CLIPPING, "D3DRS_CLIPPING"},
290  {SC_RENDERSTATE, D3DRS_LIGHTING, "D3DRS_LIGHTING"}, /* 0x30 */
291  {SC_RENDERSTATE, D3DRS_AMBIENT, "D3DRS_AMBIENT"},
292  {SC_RENDERSTATE, D3DRS_FOGVERTEXMODE, "D3DRS_FOGVERTEXMODE"},
293  {SC_RENDERSTATE, D3DRS_COLORVERTEX, "D3DRS_COLORVERTEX"},
294  {SC_RENDERSTATE, D3DRS_LOCALVIEWER, "D3DRS_LOCALVIEWER"},
295  {SC_RENDERSTATE, D3DRS_NORMALIZENORMALS, "D3DRS_NORMALIZENORMALS"},
296  {SC_RENDERSTATE, D3DRS_DIFFUSEMATERIALSOURCE, "D3DRS_DIFFUSEMATERIALSOURCE"},
297  {SC_RENDERSTATE, D3DRS_SPECULARMATERIALSOURCE, "D3DRS_SPECULARMATERIALSOURCE"},
298  {SC_RENDERSTATE, D3DRS_AMBIENTMATERIALSOURCE, "D3DRS_AMBIENTMATERIALSOURCE"},
299  {SC_RENDERSTATE, D3DRS_EMISSIVEMATERIALSOURCE, "D3DRS_EMISSIVEMATERIALSOURCE"},
300  {SC_RENDERSTATE, D3DRS_VERTEXBLEND, "D3DRS_VERTEXBLEND"},
301  {SC_RENDERSTATE, D3DRS_CLIPPLANEENABLE, "D3DRS_CLIPPLANEENABLE"},
302  {SC_RENDERSTATE, D3DRS_POINTSIZE, "D3DRS_POINTSIZE"},
303  {SC_RENDERSTATE, D3DRS_POINTSIZE_MIN, "D3DRS_POINTSIZE_MIN"},
304  {SC_RENDERSTATE, D3DRS_POINTSIZE_MAX, "D3DRS_POINTSIZE_MAX"},
305  {SC_RENDERSTATE, D3DRS_POINTSPRITEENABLE, "D3DRS_POINTSPRITEENABLE"},
306  {SC_RENDERSTATE, D3DRS_POINTSCALEENABLE, "D3DRS_POINTSCALEENABLE"}, /* 0x40 */
307  {SC_RENDERSTATE, D3DRS_POINTSCALE_A, "D3DRS_POINTSCALE_A"},
308  {SC_RENDERSTATE, D3DRS_POINTSCALE_B, "D3DRS_POINTSCALE_B"},
309  {SC_RENDERSTATE, D3DRS_POINTSCALE_C, "D3DRS_POINTSCALE_C"},
310  {SC_RENDERSTATE, D3DRS_MULTISAMPLEANTIALIAS, "D3DRS_MULTISAMPLEANTIALIAS"},
311  {SC_RENDERSTATE, D3DRS_MULTISAMPLEMASK, "D3DRS_MULTISAMPLEMASK"},
312  {SC_RENDERSTATE, D3DRS_PATCHEDGESTYLE, "D3DRS_PATCHEDGESTYLE"},
313  {SC_RENDERSTATE, D3DRS_DEBUGMONITORTOKEN, "D3DRS_DEBUGMONITORTOKEN"},
314  {SC_RENDERSTATE, D3DRS_INDEXEDVERTEXBLENDENABLE, "D3DRS_INDEXEDVERTEXBLENDENABLE"},
315  {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE, "D3DRS_COLORWRITEENABLE"},
316  {SC_RENDERSTATE, D3DRS_TWEENFACTOR, "D3DRS_TWEENFACTOR"},
317  {SC_RENDERSTATE, D3DRS_BLENDOP, "D3DRS_BLENDOP"},
318  {SC_RENDERSTATE, D3DRS_POSITIONDEGREE, "D3DRS_POSITIONDEGREE"},
319  {SC_RENDERSTATE, D3DRS_NORMALDEGREE, "D3DRS_NORMALDEGREE"},
320  {SC_RENDERSTATE, D3DRS_SCISSORTESTENABLE, "D3DRS_SCISSORTESTENABLE"},
321  {SC_RENDERSTATE, D3DRS_SLOPESCALEDEPTHBIAS, "D3DRS_SLOPESCALEDEPTHBIAS"},
322  {SC_RENDERSTATE, D3DRS_ANTIALIASEDLINEENABLE, "D3DRS_ANTIALIASEDLINEENABLE"}, /* 0x50 */
323  {SC_RENDERSTATE, D3DRS_MINTESSELLATIONLEVEL, "D3DRS_MINTESSELLATIONLEVEL"},
324  {SC_RENDERSTATE, D3DRS_MAXTESSELLATIONLEVEL, "D3DRS_MAXTESSELLATIONLEVEL"},
325  {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_X, "D3DRS_ADAPTIVETESS_X"},
326  {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_Y, "D3DRS_ADAPTIVETESS_Y"},
327  {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_Z, "D3DRS_ADAPTIVETESS_Z"},
328  {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_W, "D3DRS_ADAPTIVETESS_W"},
329  {SC_RENDERSTATE, D3DRS_ENABLEADAPTIVETESSELLATION, "D3DRS_ENABLEADAPTIVETESSELLATION"},
330  {SC_RENDERSTATE, D3DRS_TWOSIDEDSTENCILMODE, "D3DRS_TWOSIDEDSTENCILMODE"},
331  {SC_RENDERSTATE, D3DRS_CCW_STENCILFAIL, "D3DRS_CCW_STENCILFAIL"},
332  {SC_RENDERSTATE, D3DRS_CCW_STENCILZFAIL, "D3DRS_CCW_STENCILZFAIL"},
333  {SC_RENDERSTATE, D3DRS_CCW_STENCILPASS, "D3DRS_CCW_STENCILPASS"},
334  {SC_RENDERSTATE, D3DRS_CCW_STENCILFUNC, "D3DRS_CCW_STENCILFUNC"},
335  {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE1, "D3DRS_COLORWRITEENABLE1"},
336  {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE2, "D3DRS_COLORWRITEENABLE2"},
337  {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE3, "D3DRS_COLORWRITEENABLE3"},
338  {SC_RENDERSTATE, D3DRS_BLENDFACTOR, "D3DRS_BLENDFACTOR"}, /* 0x60 */
339  {SC_RENDERSTATE, D3DRS_SRGBWRITEENABLE, "D3DRS_SRGBWRITEENABLE"},
340  {SC_RENDERSTATE, D3DRS_DEPTHBIAS, "D3DRS_DEPTHBIAS"},
341  {SC_RENDERSTATE, D3DRS_SEPARATEALPHABLENDENABLE, "D3DRS_SEPARATEALPHABLENDENABLE"},
342  {SC_RENDERSTATE, D3DRS_SRCBLENDALPHA, "D3DRS_SRCBLENDALPHA"},
343  {SC_RENDERSTATE, D3DRS_DESTBLENDALPHA, "D3DRS_DESTBLENDALPHA"},
344  {SC_RENDERSTATE, D3DRS_BLENDOPALPHA, "D3DRS_BLENDOPALPHA"},
345  /* Texture stages */
346  {SC_TEXTURESTAGE, D3DTSS_COLOROP, "D3DTSS_COLOROP"},
347  {SC_TEXTURESTAGE, D3DTSS_COLORARG0, "D3DTSS_COLORARG0"},
348  {SC_TEXTURESTAGE, D3DTSS_COLORARG1, "D3DTSS_COLORARG1"},
349  {SC_TEXTURESTAGE, D3DTSS_COLORARG2, "D3DTSS_COLORARG2"},
350  {SC_TEXTURESTAGE, D3DTSS_ALPHAOP, "D3DTSS_ALPHAOP"},
351  {SC_TEXTURESTAGE, D3DTSS_ALPHAARG0, "D3DTSS_ALPHAARG0"},
352  {SC_TEXTURESTAGE, D3DTSS_ALPHAARG1, "D3DTSS_ALPHAARG1"},
353  {SC_TEXTURESTAGE, D3DTSS_ALPHAARG2, "D3DTSS_ALPHAARG2"},
354  {SC_TEXTURESTAGE, D3DTSS_RESULTARG, "D3DTSS_RESULTARG"},
355  {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT00, "D3DTSS_BUMPENVMAT00"}, /* 0x70 */
356  {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT01, "D3DTSS_BUMPENVMAT01"},
357  {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT10, "D3DTSS_BUMPENVMAT10"},
358  {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT11, "D3DTSS_BUMPENVMAT11"},
359  {SC_TEXTURESTAGE, D3DTSS_TEXCOORDINDEX, "D3DTSS_TEXCOORDINDEX"},
360  {SC_TEXTURESTAGE, D3DTSS_BUMPENVLSCALE, "D3DTSS_BUMPENVLSCALE"},
361  {SC_TEXTURESTAGE, D3DTSS_BUMPENVLOFFSET, "D3DTSS_BUMPENVLOFFSET"},
362  {SC_TEXTURESTAGE, D3DTSS_TEXTURETRANSFORMFLAGS, "D3DTSS_TEXTURETRANSFORMFLAGS"},
363  {SC_TEXTURESTAGE, D3DTSS_CONSTANT, "D3DTSS_CONSTANT"},
364  /* NPatchMode */
365  {SC_NPATCHMODE, 0, "NPatchMode"},
366  /* FVF */
367  {SC_FVF, 0, "FVF"},
368  /* Transform */
369  {SC_TRANSFORM, D3DTS_PROJECTION, "D3DTS_PROJECTION"},
370  {SC_TRANSFORM, D3DTS_VIEW, "D3DTS_VIEW"},
371  {SC_TRANSFORM, D3DTS_WORLD, "D3DTS_WORLD"},
372  {SC_TRANSFORM, D3DTS_TEXTURE0, "D3DTS_TEXTURE0"},
373  /* Material */
374  {SC_MATERIAL, MT_DIFFUSE, "MaterialDiffuse"},
375  {SC_MATERIAL, MT_AMBIENT, "MaterialAmbient"}, /* 0x80 */
376  {SC_MATERIAL, MT_SPECULAR, "MaterialSpecular"},
377  {SC_MATERIAL, MT_EMISSIVE, "MaterialEmissive"},
378  {SC_MATERIAL, MT_POWER, "MaterialPower"},
379  /* Light */
380  {SC_LIGHT, LT_TYPE, "LightType"},
381  {SC_LIGHT, LT_DIFFUSE, "LightDiffuse"},
382  {SC_LIGHT, LT_SPECULAR, "LightSpecular"},
383  {SC_LIGHT, LT_AMBIENT, "LightAmbient"},
384  {SC_LIGHT, LT_POSITION, "LightPosition"},
385  {SC_LIGHT, LT_DIRECTION, "LightDirection"},
386  {SC_LIGHT, LT_RANGE, "LightRange"},
387  {SC_LIGHT, LT_FALLOFF, "LightFallOff"},
388  {SC_LIGHT, LT_ATTENUATION0, "LightAttenuation0"},
389  {SC_LIGHT, LT_ATTENUATION1, "LightAttenuation1"},
390  {SC_LIGHT, LT_ATTENUATION2, "LightAttenuation2"},
391  {SC_LIGHT, LT_THETA, "LightTheta"},
392  {SC_LIGHT, LT_PHI, "LightPhi"}, /* 0x90 */
393  /* Lightenable */
394  {SC_LIGHTENABLE, 0, "LightEnable"},
395  /* Vertexshader */
396  {SC_VERTEXSHADER, 0, "Vertexshader"},
397  /* Pixelshader */
398  {SC_PIXELSHADER, 0, "Pixelshader"},
399  /* Shader constants */
400  {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstantF"},
401  {SC_SHADERCONST, SCT_VSBOOL, "VertexShaderConstantB"},
402  {SC_SHADERCONST, SCT_VSINT, "VertexShaderConstantI"},
403  {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant"},
404  {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant1"},
405  {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant2"},
406  {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant3"},
407  {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant4"},
408  {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstantF"},
409  {SC_SHADERCONST, SCT_PSBOOL, "PixelShaderConstantB"},
410  {SC_SHADERCONST, SCT_PSINT, "PixelShaderConstantI"},
411  {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant"},
412  {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant1"}, /* 0xa0 */
413  {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant2"},
414  {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant3"},
415  {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant4"},
416  /* Texture */
417  {SC_TEXTURE, 0, "Texture"},
418  /* Sampler states */
419  {SC_SAMPLERSTATE, D3DSAMP_ADDRESSU, "AddressU"},
420  {SC_SAMPLERSTATE, D3DSAMP_ADDRESSV, "AddressV"},
421  {SC_SAMPLERSTATE, D3DSAMP_ADDRESSW, "AddressW"},
422  {SC_SAMPLERSTATE, D3DSAMP_BORDERCOLOR, "BorderColor"},
423  {SC_SAMPLERSTATE, D3DSAMP_MAGFILTER, "MagFilter"},
424  {SC_SAMPLERSTATE, D3DSAMP_MINFILTER, "MinFilter"},
425  {SC_SAMPLERSTATE, D3DSAMP_MIPFILTER, "MipFilter"},
426  {SC_SAMPLERSTATE, D3DSAMP_MIPMAPLODBIAS, "MipMapLodBias"},
427  {SC_SAMPLERSTATE, D3DSAMP_MAXMIPLEVEL, "MaxMipLevel"},
428  {SC_SAMPLERSTATE, D3DSAMP_MAXANISOTROPY, "MaxAnisotropy"},
429  {SC_SAMPLERSTATE, D3DSAMP_SRGBTEXTURE, "SRGBTexture"},
430  {SC_SAMPLERSTATE, D3DSAMP_ELEMENTINDEX, "ElementIndex"}, /* 0xb0 */
431  {SC_SAMPLERSTATE, D3DSAMP_DMAPOFFSET, "DMAPOffset"},
432  /* Set sampler */
433  {SC_SETSAMPLER, 0, "Sampler"},
434 };
435 
436 static inline void read_dword(const char **ptr, DWORD *d)
437 {
438  memcpy(d, *ptr, sizeof(*d));
439  *ptr += sizeof(*d);
440 }
441 
442 static void skip_dword_unknown(const char **ptr, unsigned int count)
443 {
444  unsigned int i;
445  DWORD d;
446 
447  WARN("Skipping %u unknown DWORDs:\n", count);
448  for (i = 0; i < count; ++i)
449  {
450  read_dword(ptr, &d);
451  WARN("\t0x%08x\n", d);
452  }
453 }
454 
455 static inline D3DXHANDLE get_parameter_handle(struct d3dx_parameter *parameter)
456 {
457  return (D3DXHANDLE)parameter;
458 }
459 
460 static inline D3DXHANDLE get_technique_handle(struct d3dx_technique *technique)
461 {
462  return (D3DXHANDLE)technique;
463 }
464 
465 static inline D3DXHANDLE get_pass_handle(struct d3dx_pass *pass)
466 {
467  return (D3DXHANDLE)pass;
468 }
469 
470 static struct d3dx_technique *get_technique_by_name(struct d3dx_effect *effect, const char *name)
471 {
472  unsigned int i;
473 
474  if (!name) return NULL;
475 
476  for (i = 0; i < effect->technique_count; ++i)
477  {
478  if (!strcmp(effect->techniques[i].name, name))
479  return &effect->techniques[i];
480  }
481 
482  return NULL;
483 }
484 
485 static struct d3dx_technique *get_valid_technique(struct d3dx_effect *effect, D3DXHANDLE technique)
486 {
487  unsigned int i;
488 
489  for (i = 0; i < effect->technique_count; ++i)
490  {
491  if (get_technique_handle(&effect->techniques[i]) == technique)
492  return &effect->techniques[i];
493  }
494 
495  return get_technique_by_name(effect, technique);
496 }
497 
498 static struct d3dx_pass *get_valid_pass(struct d3dx_effect *effect, D3DXHANDLE pass)
499 {
500  unsigned int i, k;
501 
502  for (i = 0; i < effect->technique_count; ++i)
503  {
504  struct d3dx_technique *technique = &effect->techniques[i];
505 
506  for (k = 0; k < technique->pass_count; ++k)
507  {
508  if (get_pass_handle(&technique->passes[k]) == pass)
509  return &technique->passes[k];
510  }
511  }
512 
513  return NULL;
514 }
515 
516 static struct d3dx_parameter *get_valid_parameter(struct d3dx_effect *effect, D3DXHANDLE parameter)
517 {
518  struct d3dx_parameter *handle_param = (struct d3dx_parameter *)parameter;
519 
520  if (handle_param && !strncmp(handle_param->magic_string, parameter_magic_string,
521  sizeof(parameter_magic_string)))
522  return handle_param;
523 
524  return effect->flags & D3DXFX_LARGEADDRESSAWARE ? NULL : get_parameter_by_name(effect, NULL, parameter);
525 }
526 
528 {
530 
531  return block && !strncmp(block->magic_string, parameter_block_magic_string,
533 }
534 
535 static void free_state(struct d3dx_state *state)
536 {
537  free_parameter(&state->parameter, FALSE, FALSE);
538 }
539 
540 static void free_object(struct d3dx_object *object)
541 {
542  HeapFree(GetProcessHeap(), 0, object->data);
543 }
544 
545 static void free_sampler(struct d3dx_sampler *sampler)
546 {
547  UINT i;
548 
549  for (i = 0; i < sampler->state_count; ++i)
550  {
551  free_state(&sampler->states[i]);
552  }
553  heap_free(sampler->states);
554 }
555 
557 
558 static void free_parameter_object_data(struct d3dx_parameter *param, const void *data, unsigned int bytes)
559 {
560  unsigned int i, count;
561 
562  if (param->class != D3DXPC_OBJECT)
563  return;
564 
565  count = min(param->element_count ? param->element_count : 1, bytes / sizeof(void *));
566 
567  for (i = 0; i < count; ++i)
568  {
569  switch (param->type)
570  {
571  case D3DXPT_STRING:
572  heap_free(((char **)data)[i]);
573  break;
574 
575  case D3DXPT_TEXTURE:
576  case D3DXPT_TEXTURE1D:
577  case D3DXPT_TEXTURE2D:
578  case D3DXPT_TEXTURE3D:
579  case D3DXPT_TEXTURECUBE:
580  case D3DXPT_PIXELSHADER:
581  case D3DXPT_VERTEXSHADER:
582  if (*(IUnknown **)data)
583  IUnknown_Release(((IUnknown **)data)[i]);
584  break;
585 
586  case D3DXPT_SAMPLER:
587  case D3DXPT_SAMPLER1D:
588  case D3DXPT_SAMPLER2D:
589  case D3DXPT_SAMPLER3D:
590  case D3DXPT_SAMPLERCUBE:
591  assert(count == 1);
592  free_sampler((struct d3dx_sampler *)data);
593  return;
594 
595  default:
596  FIXME("Unhandled type %s\n", debug_d3dxparameter_type(param->type));
597  break;
598  }
599  }
600 }
601 
603 {
604  if (!param->data)
605  return;
606 
607  if (!param->element_count)
609 
610  if (!child || is_param_type_sampler(param->type))
611  heap_free(param->data);
612 }
613 
615 {
616  unsigned int i;
617 
618  TRACE("Free parameter %p, name %s, type %s, element %#x, child %#x.\n", param, param->name,
620 
621  if (param->param_eval)
622  d3dx_free_param_eval(param->param_eval);
623 
624  if (param->members)
625  {
626  unsigned int count = param->element_count ? param->element_count : param->member_count;
627 
628  for (i = 0; i < count; ++i)
629  free_parameter(&param->members[i], param->element_count != 0, TRUE);
630  HeapFree(GetProcessHeap(), 0, param->members);
631  }
632 
633  heap_free(param->full_name);
635 
636  /* only the parent has to release name and semantic */
637  if (!element)
638  {
640  HeapFree(GetProcessHeap(), 0, param->semantic);
641  }
642 }
643 
645 {
646  if (param->annotations)
647  {
648  unsigned int i;
649 
650  for (i = 0; i < param->annotation_count; ++i)
651  free_parameter(&param->annotations[i], FALSE, FALSE);
652  HeapFree(GetProcessHeap(), 0, param->annotations);
653  }
655  free_parameter(&param->param, FALSE, FALSE);
656 }
657 
658 static void free_pass(struct d3dx_pass *pass)
659 {
660  unsigned int i;
661 
662  TRACE("Free pass %p\n", pass);
663 
664  if (!pass)
665  return;
666 
667  if (pass->annotations)
668  {
669  for (i = 0; i < pass->annotation_count; ++i)
670  free_parameter(&pass->annotations[i], FALSE, FALSE);
671  HeapFree(GetProcessHeap(), 0, pass->annotations);
672  pass->annotations = NULL;
673  }
674 
675  if (pass->states)
676  {
677  for (i = 0; i < pass->state_count; ++i)
678  free_state(&pass->states[i]);
679  HeapFree(GetProcessHeap(), 0, pass->states);
680  pass->states = NULL;
681  }
682 
684  pass->name = NULL;
685 }
686 
687 static void free_technique(struct d3dx_technique *technique)
688 {
689  unsigned int i;
690 
691  TRACE("Free technique %p\n", technique);
692 
693  if (!technique)
694  return;
695 
696  if (technique->saved_state)
697  {
699  technique->saved_state = NULL;
700  }
701 
702  if (technique->annotations)
703  {
704  for (i = 0; i < technique->annotation_count; ++i)
705  free_parameter(&technique->annotations[i], FALSE, FALSE);
706  HeapFree(GetProcessHeap(), 0, technique->annotations);
707  technique->annotations = NULL;
708  }
709 
710  if (technique->passes)
711  {
712  for (i = 0; i < technique->pass_count; ++i)
713  free_pass(&technique->passes[i]);
714  HeapFree(GetProcessHeap(), 0, technique->passes);
715  technique->passes = NULL;
716  }
717 
718  HeapFree(GetProcessHeap(), 0, technique->name);
719  technique->name = NULL;
720 }
721 
723 {
724  return sizeof(*record) + record->bytes;
725 }
726 
728 {
730 
731  if (!block)
732  return;
733 
734  record = (struct d3dx_recorded_parameter *)block->buffer;
735  while ((BYTE *)record < block->buffer + block->offset)
736  {
737  free_parameter_object_data(record->param, record + 1, record->bytes);
739  }
740  assert((BYTE *)record == block->buffer + block->offset);
741 
742  heap_free(block->buffer);
743  heap_free(block);
744 }
745 
746 static void d3dx_effect_cleanup(struct d3dx_effect *effect)
747 {
749  ID3DXEffectPool *pool;
750  unsigned int i;
751 
752  TRACE("effect %p.\n", effect);
753 
754  free_parameter_block(effect->current_parameter_block);
755  LIST_FOR_EACH_ENTRY_SAFE(block, cursor, &effect->parameter_block_list, struct d3dx_parameter_block, entry)
756  {
757  list_remove(&block->entry);
759  }
760 
761  heap_free(effect->full_name_tmp);
762 
763  if (effect->parameters)
764  {
765  for (i = 0; i < effect->parameter_count; ++i)
766  free_top_level_parameter(&effect->parameters[i]);
767  heap_free(effect->parameters);
768  }
769 
770  if (effect->techniques)
771  {
772  for (i = 0; i < effect->technique_count; ++i)
773  free_technique(&effect->techniques[i]);
774  heap_free(effect->techniques);
775  }
776 
777  if (effect->objects)
778  {
779  for (i = 0; i < effect->object_count; ++i)
780  free_object(&effect->objects[i]);
781  heap_free(effect->objects);
782  }
783 
784  if (effect->pool)
785  {
786  pool = &effect->pool->ID3DXEffectPool_iface;
787  pool->lpVtbl->Release(pool);
788  }
789 
790  if (effect->manager)
791  IUnknown_Release(effect->manager);
792 
794  heap_free(effect);
795 }
796 
798 {
799  UINT i;
800 
801  for (i = 0; i < 4; ++i)
802  {
803  if (i < param->columns)
804  set_number((FLOAT *)vector + i, D3DXPT_FLOAT, (DWORD *)param->data + i, param->type);
805  else
806  ((FLOAT *)vector)[i] = 0.0f;
807  }
808 }
809 
810 static void set_vector(struct d3dx_parameter *param, const D3DXVECTOR4 *vector, void *dst_data)
811 {
812  UINT i;
813 
814  for (i = 0; i < param->columns; ++i)
815  set_number((FLOAT *)dst_data + i, param->type, (FLOAT *)vector + i, D3DXPT_FLOAT);
816 }
817 
819 {
820  UINT i, k;
821 
822  for (i = 0; i < 4; ++i)
823  {
824  for (k = 0; k < 4; ++k)
825  {
826  FLOAT *tmp = transpose ? (FLOAT *)&matrix->u.m[k][i] : (FLOAT *)&matrix->u.m[i][k];
827 
828  if ((i < param->rows) && (k < param->columns))
829  set_number(tmp, D3DXPT_FLOAT, (DWORD *)param->data + i * param->columns + k, param->type);
830  else
831  *tmp = 0.0f;
832  }
833  }
834 }
835 
836 static void set_matrix(struct d3dx_parameter *param, const D3DXMATRIX *matrix, void *dst_data)
837 {
838  UINT i, k;
839 
840  if (param->type == D3DXPT_FLOAT)
841  {
842  if (param->columns == 4)
843  {
844  memcpy(dst_data, matrix->u.m, param->rows * 4 * sizeof(float));
845  }
846  else
847  {
848  for (i = 0; i < param->rows; ++i)
849  memcpy((float *)dst_data + i * param->columns, matrix->u.m + i, param->columns * sizeof(float));
850  }
851  return;
852  }
853 
854  for (i = 0; i < param->rows; ++i)
855  {
856  for (k = 0; k < param->columns; ++k)
857  set_number((FLOAT *)dst_data + i * param->columns + k, param->type,
858  &matrix->u.m[i][k], D3DXPT_FLOAT);
859  }
860 }
861 
862 static void set_matrix_transpose(struct d3dx_parameter *param, const D3DXMATRIX *matrix, void *dst_data)
863 {
864  UINT i, k;
865 
866  for (i = 0; i < param->rows; ++i)
867  {
868  for (k = 0; k < param->columns; ++k)
869  {
870  set_number((FLOAT *)dst_data + i * param->columns + k, param->type,
871  &matrix->u.m[k][i], D3DXPT_FLOAT);
872  }
873  }
874 }
875 
876 static HRESULT set_string(char **param_data, const char *string)
877 {
878  heap_free(*param_data);
879  *param_data = heap_alloc(strlen(string) + 1);
880  if (!*param_data)
881  {
882  ERR("Out of memory.\n");
883  return E_OUTOFMEMORY;
884  }
885  strcpy(*param_data, string);
886  return D3D_OK;
887 }
888 
889 static HRESULT set_value(struct d3dx_parameter *param, const void *data, unsigned int bytes,
890  void *dst_data)
891 {
892  unsigned int i, count;
893 
894  bytes = min(bytes, param->bytes);
895  count = min(param->element_count ? param->element_count : 1, bytes / sizeof(void *));
896 
897  switch (param->type)
898  {
899  case D3DXPT_TEXTURE:
900  case D3DXPT_TEXTURE1D:
901  case D3DXPT_TEXTURE2D:
902  case D3DXPT_TEXTURE3D:
903  case D3DXPT_TEXTURECUBE:
904  for (i = 0; i < count; ++i)
905  {
906  IUnknown *old_texture = ((IUnknown **)dst_data)[i];
907  IUnknown *new_texture = ((IUnknown **)data)[i];
908 
909  if (new_texture == old_texture)
910  continue;
911 
912  if (new_texture)
913  IUnknown_AddRef(new_texture);
914  if (old_texture)
915  IUnknown_Release(old_texture);
916  }
917  /* fallthrough */
918  case D3DXPT_VOID:
919  case D3DXPT_BOOL:
920  case D3DXPT_INT:
921  case D3DXPT_FLOAT:
922  TRACE("Copy %u bytes.\n", bytes);
923  memcpy(dst_data, data, bytes);
924  break;
925 
926  case D3DXPT_STRING:
927  {
928  HRESULT hr;
929 
930  for (i = 0; i < count; ++i)
931  if (FAILED(hr = set_string(&((char **)dst_data)[i], ((const char **)data)[i])))
932  return hr;
933  break;
934  }
935 
936  default:
937  FIXME("Unhandled type %s.\n", debug_d3dxparameter_type(param->type));
938  break;
939  }
940 
941  return D3D_OK;
942 }
943 
945  struct d3dx_parameter *parameter, const char *name)
946 {
947  UINT element;
948  struct d3dx_parameter *temp_parameter;
949  const char *part;
950 
951  TRACE("parameter %p, name %s\n", parameter, debugstr_a(name));
952 
953  if (!name || !*name) return NULL;
954 
955  element = atoi(name);
956  part = strchr(name, ']') + 1;
957 
958  /* check for empty [] && element range */
959  if ((part - name) > 1 && parameter->element_count > element)
960  {
961  temp_parameter = &parameter->members[element];
962 
963  switch (*part++)
964  {
965  case '.':
966  return get_parameter_by_name(effect, temp_parameter, part);
967 
968  case '\0':
969  TRACE("Returning parameter %p\n", temp_parameter);
970  return temp_parameter;
971 
972  default:
973  FIXME("Unhandled case \"%c\"\n", *--part);
974  break;
975  }
976  }
977 
978  TRACE("Parameter not found\n");
979  return NULL;
980 }
981 
982 static struct d3dx_parameter *get_annotation_by_name(struct d3dx_effect *effect, unsigned int count,
983  struct d3dx_parameter *annotations, const char *name)
984 {
985  UINT i, length;
986  struct d3dx_parameter *temp_parameter;
987  const char *part;
988 
989  TRACE("count %u, annotations %p, name %s\n", count, annotations, debugstr_a(name));
990 
991  if (!name || !*name) return NULL;
992 
993  length = strcspn( name, "[.@" );
994  part = name + length;
995 
996  for (i = 0; i < count; ++i)
997  {
998  temp_parameter = &annotations[i];
999 
1000  if (!strcmp(temp_parameter->name, name))
1001  {
1002  TRACE("Returning annotation %p\n", temp_parameter);
1003  return temp_parameter;
1004  }
1005  else if (strlen(temp_parameter->name) == length && !strncmp(temp_parameter->name, name, length))
1006  {
1007  switch (*part++)
1008  {
1009  case '.':
1010  return get_parameter_by_name(effect, temp_parameter, part);
1011 
1012  case '[':
1013  return get_parameter_element_by_name(effect, temp_parameter, part);
1014 
1015  default:
1016  FIXME("Unhandled case \"%c\"\n", *--part);
1017  break;
1018  }
1019  }
1020  }
1021 
1022  TRACE("Annotation not found\n");
1023  return NULL;
1024 }
1025 
1027  struct d3dx_parameter *parameter, const char *name)
1028 {
1029  struct d3dx_parameter *temp_parameter;
1030  unsigned int name_len, param_name_len;
1031  unsigned int i, count, length;
1032  struct wine_rb_entry *entry;
1033  unsigned int full_name_size;
1034  const char *part;
1035  char *full_name;
1036 
1037  TRACE("effect %p, parameter %p, name %s.\n", effect, parameter, debugstr_a(name));
1038 
1039  if (!name || !*name) return NULL;
1040 
1041  if (!parameter)
1042  {
1043  if ((entry = wine_rb_get(&effect->param_tree, name)))
1045  return NULL;
1046  }
1047 
1048  if (parameter->full_name)
1049  {
1050  name_len = strlen(name);
1051  param_name_len = strlen(parameter->full_name);
1052  full_name_size = name_len + param_name_len + 2;
1053  if (effect->full_name_tmp_size < full_name_size)
1054  {
1055  if (!(full_name = heap_realloc(effect->full_name_tmp, full_name_size)))
1056  {
1057  ERR("Out of memory.\n");
1058  return NULL;
1059  }
1060  effect->full_name_tmp = full_name;
1061  effect->full_name_tmp_size = full_name_size;
1062  }
1063  else
1064  {
1065  full_name = effect->full_name_tmp;
1066  }
1067  memcpy(full_name, parameter->full_name, param_name_len);
1068  full_name[param_name_len] = '.';
1069  memcpy(full_name + param_name_len + 1, name, name_len);
1070  full_name[param_name_len + 1 + name_len] = 0;
1071 
1072  if ((entry = wine_rb_get(&effect->param_tree, full_name)))
1074  return NULL;
1075  }
1076 
1077  /* Pass / technique annotations are not stored in the parameters tree,
1078  * do a linear search. */
1079  count = parameter->member_count;
1080 
1081  length = strcspn( name, "[." );
1082  part = name + length;
1083 
1084  for (i = 0; i < count; i++)
1085  {
1086  temp_parameter = &parameter->members[i];
1087 
1088  if (!strcmp(temp_parameter->name, name))
1089  {
1090  TRACE("Returning parameter %p\n", temp_parameter);
1091  return temp_parameter;
1092  }
1093  else if (strlen(temp_parameter->name) == length && !strncmp(temp_parameter->name, name, length))
1094  {
1095  switch (*part++)
1096  {
1097  case '.':
1098  return get_parameter_by_name(effect, temp_parameter, part);
1099 
1100  case '[':
1101  return get_parameter_element_by_name(effect, temp_parameter, part);
1102 
1103  default:
1104  FIXME("Unhandled case \"%c\"\n", *--part);
1105  break;
1106  }
1107  }
1108  }
1109 
1110  TRACE("Parameter not found\n");
1111  return NULL;
1112 }
1113 
1115 {
1116  return (0xfeff0000 | ((major) << 8) | (minor));
1117 }
1118 
1120  void **param_value, struct d3dx_parameter **out_param,
1121  BOOL update_all, BOOL *param_dirty)
1122 {
1123  struct d3dx_parameter *param = &state->parameter;
1124 
1125  *param_value = NULL;
1126  *out_param = NULL;
1127  *param_dirty = FALSE;
1128 
1129  switch (state->type)
1130  {
1131  case ST_PARAMETER:
1132  param = state->referenced_param;
1133  *param_dirty = is_param_dirty(param, pass->update_version);
1134  /* fallthrough */
1135  case ST_CONSTANT:
1136  *out_param = param;
1137  *param_value = param->data;
1138  return D3D_OK;
1139  case ST_ARRAY_SELECTOR:
1140  {
1141  unsigned int array_idx;
1142  static const struct d3dx_parameter array_idx_param =
1143  {"", NULL, NULL, NULL, NULL, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 0, 0, 0, sizeof(array_idx)};
1144  HRESULT hr;
1145  struct d3dx_parameter *ref_param, *selected_param;
1146 
1147  if (!param->param_eval)
1148  {
1149  FIXME("Preshader structure is null.\n");
1150  return D3DERR_INVALIDCALL;
1151  }
1152  /* We override with the update_version of the pass because we want
1153  * to force index recomputation and check for out of bounds. */
1154  if (is_param_eval_input_dirty(param->param_eval, pass->update_version))
1155  {
1156  if (FAILED(hr = d3dx_evaluate_parameter(param->param_eval, &array_idx_param, &array_idx)))
1157  return hr;
1158  }
1159  else
1160  {
1161  array_idx = state->index;
1162  }
1163  ref_param = state->referenced_param;
1164  TRACE("Array index %u, stored array index %u, element_count %u.\n", array_idx, state->index,
1165  ref_param->element_count);
1166  /* According to the tests, native d3dx handles the case of array index evaluated to -1
1167  * in a specific way, always selecting first array element and not returning error. */
1168  if (array_idx == ~0u)
1169  {
1170  WARN("Array index is -1, setting to 0.\n");
1171  array_idx = 0;
1172  }
1173 
1174  if (array_idx >= ref_param->element_count)
1175  {
1176  WARN("Computed array index %u is larger than array size %u.\n",
1177  array_idx, ref_param->element_count);
1178  return E_FAIL;
1179  }
1180  selected_param = &ref_param->members[array_idx];
1181  *param_dirty = state->index != array_idx || is_param_dirty(selected_param, pass->update_version);
1182  state->index = array_idx;
1183 
1184  *param_value = selected_param->data;
1185  *out_param = selected_param;
1186  return D3D_OK;
1187  }
1188  case ST_FXLC:
1189  if (param->param_eval)
1190  {
1191  *out_param = param;
1192  *param_value = param->data;
1193  /* We check with the update_version of the pass because the
1194  * same preshader might be used by both the vertex and the
1195  * pixel shader (that can happen e.g. for sampler states). */
1196  if (update_all || is_param_eval_input_dirty(param->param_eval, pass->update_version))
1197  {
1198  *param_dirty = TRUE;
1199  return d3dx_evaluate_parameter(param->param_eval, param, *param_value);
1200  }
1201  else
1202  return D3D_OK;
1203  }
1204  else
1205  {
1206  FIXME("No preshader for FXLC parameter.\n");
1207  return D3DERR_INVALIDCALL;
1208  }
1209  }
1210  return E_NOTIMPL;
1211 }
1212 
1213 static unsigned int get_annotation_from_object(struct d3dx_effect *effect, D3DXHANDLE object,
1214  struct d3dx_parameter **annotations)
1215 {
1216  struct d3dx_parameter *param = get_valid_parameter(effect, object);
1217  struct d3dx_pass *pass = get_valid_pass(effect, object);
1218  struct d3dx_technique *technique = get_valid_technique(effect, object);
1219 
1220  if (pass)
1221  {
1222  *annotations = pass->annotations;
1223  return pass->annotation_count;
1224  }
1225  else if (technique)
1226  {
1227  *annotations = technique->annotations;
1228  return technique->annotation_count;
1229  }
1230  else if (param)
1231  {
1233  {
1234  struct d3dx_top_level_parameter *top_param
1236 
1237  *annotations = top_param->annotations;
1238  return top_param->annotation_count;
1239  }
1240  else
1241  {
1242  *annotations = NULL;
1243  return 0;
1244  }
1245  }
1246  else
1247  {
1248  FIXME("Functions are not handled, yet!\n");
1249  return 0;
1250  }
1251 }
1252 
1254  void *data)
1255 {
1256  unsigned int i;
1257  unsigned int member_count;
1258 
1259  if (param_func(data, param))
1260  return TRUE;
1261 
1262  member_count = param->element_count ? param->element_count : param->member_count;
1263  for (i = 0; i < member_count; ++i)
1264  {
1265  if (walk_parameter_tree(&param->members[i], param_func, data))
1266  return TRUE;
1267  }
1268  return FALSE;
1269 }
1270 
1272 {
1273  return effect->pool ? &effect->pool->version_counter : &effect->version_counter;
1274 }
1275 
1277 {
1279 }
1280 
1281 static void *record_parameter(struct d3dx_effect *effect, struct d3dx_parameter *param, unsigned int bytes)
1282 {
1283  struct d3dx_parameter_block *block = effect->current_parameter_block;
1284  struct d3dx_recorded_parameter new_record, *record;
1285  unsigned int new_size, alloc_size;
1286 
1287  new_record.param = param;
1288  new_record.bytes = bytes;
1289  new_size = block->offset + get_recorded_parameter_size(&new_record);
1290 
1291  if (new_size > block->size)
1292  {
1293  BYTE *new_alloc;
1294 
1295  alloc_size = max(block->size * 2, max(new_size, INITIAL_PARAM_BLOCK_SIZE));
1296  if (block->size)
1297  new_alloc = heap_realloc(block->buffer, alloc_size);
1298  else
1299  new_alloc = heap_alloc(alloc_size);
1300 
1301  if (!new_alloc)
1302  {
1303  ERR("Out of memory.\n");
1304  return param->data;
1305  }
1306  /* Data update functions may want to free some references upon setting value. */
1307  memset(new_alloc + block->size, 0, alloc_size - block->size);
1308 
1309  block->size = alloc_size;
1310  block->buffer = new_alloc;
1311  }
1312  record = (struct d3dx_recorded_parameter *)(block->buffer + block->offset);
1313  *record = new_record;
1314  block->offset = new_size;
1315  return record + 1;
1316 }
1317 
1318 static void set_dirty(struct d3dx_parameter *param)
1319 {
1320  struct d3dx_shared_data *shared_data;
1321  struct d3dx_top_level_parameter *top_param = param->top_level_param;
1322  ULONG64 new_update_version = next_update_version(top_param->version_counter);
1323 
1324  if ((shared_data = top_param->shared_data))
1325  shared_data->update_version = new_update_version;
1326  else
1327  top_param->update_version = new_update_version;
1328 }
1329 
1330 static void *param_get_data_and_dirtify(struct d3dx_effect *effect, struct d3dx_parameter *param,
1331  unsigned int bytes, BOOL value_changed)
1332 {
1333  assert(bytes <= param->bytes);
1334 
1335  if (value_changed && !effect->current_parameter_block)
1336  set_dirty(param);
1337 
1338  return effect->current_parameter_block ? record_parameter(effect, param, bytes) : param->data;
1339 }
1340 
1342 {
1343  static const struct
1344  {
1345  unsigned int offset;
1346  const char *name;
1347  }
1348  light_tbl[] =
1349  {
1350  {FIELD_OFFSET(D3DLIGHT9, Type), "LC_TYPE"},
1351  {FIELD_OFFSET(D3DLIGHT9, Diffuse), "LT_DIFFUSE"},
1352  {FIELD_OFFSET(D3DLIGHT9, Specular), "LT_SPECULAR"},
1353  {FIELD_OFFSET(D3DLIGHT9, Ambient), "LT_AMBIENT"},
1354  {FIELD_OFFSET(D3DLIGHT9, Position), "LT_POSITION"},
1355  {FIELD_OFFSET(D3DLIGHT9, Direction), "LT_DIRECTION"},
1356  {FIELD_OFFSET(D3DLIGHT9, Range), "LT_RANGE"},
1357  {FIELD_OFFSET(D3DLIGHT9, Falloff), "LT_FALLOFF"},
1358  {FIELD_OFFSET(D3DLIGHT9, Attenuation0), "LT_ATTENUATION0"},
1359  {FIELD_OFFSET(D3DLIGHT9, Attenuation1), "LT_ATTENUATION1"},
1360  {FIELD_OFFSET(D3DLIGHT9, Attenuation2), "LT_ATTENUATION2"},
1361  {FIELD_OFFSET(D3DLIGHT9, Theta), "LT_THETA"},
1362  {FIELD_OFFSET(D3DLIGHT9, Phi), "LT_PHI"}
1363  };
1364  switch (op)
1365  {
1366  case LT_TYPE:
1367  TRACE("LT_TYPE %u.\n", *(D3DLIGHTTYPE *)value);
1368  light->Type = *(D3DLIGHTTYPE *)value;
1369  break;
1370  case LT_DIFFUSE:
1371  case LT_SPECULAR:
1372  case LT_AMBIENT:
1373  {
1375 
1376  TRACE("%s (%.8e %.8e %.8e %.8e).\n", light_tbl[op].name, c.r, c.g, c.b, c.a);
1377  *(D3DCOLORVALUE *)((BYTE *)light + light_tbl[op].offset) = c;
1378  break;
1379  }
1380  case LT_POSITION:
1381  case LT_DIRECTION:
1382  {
1383  D3DVECTOR v = *(D3DVECTOR *)value;
1384 
1385  TRACE("%s (%.8e %.8e %.8e).\n", light_tbl[op].name, v.x, v.y, v.z);
1386  *(D3DVECTOR *)((BYTE *)light + light_tbl[op].offset) = v;
1387  break;
1388  }
1389  case LT_RANGE:
1390  case LT_FALLOFF:
1391  case LT_ATTENUATION0:
1392  case LT_ATTENUATION1:
1393  case LT_ATTENUATION2:
1394  case LT_THETA:
1395  case LT_PHI:
1396  {
1397  float v = *(float *)value;
1398  TRACE("%s %.8e.\n", light_tbl[op].name, v);
1399  *(float *)((BYTE *)light + light_tbl[op].offset) = v;
1400  break;
1401  }
1402  default:
1403  WARN("Unknown light parameter %u.\n", op);
1404  break;
1405  }
1406 }
1407 
1409 {
1410  static const struct
1411  {
1412  unsigned int offset;
1413  const char *name;
1414  }
1415  material_tbl[] =
1416  {
1417  {FIELD_OFFSET(D3DMATERIAL9, Diffuse), "MT_DIFFUSE"},
1418  {FIELD_OFFSET(D3DMATERIAL9, Ambient), "MT_AMBIENT"},
1419  {FIELD_OFFSET(D3DMATERIAL9, Specular), "MT_SPECULAR"},
1420  {FIELD_OFFSET(D3DMATERIAL9, Emissive), "MT_EMISSIVE"},
1421  {FIELD_OFFSET(D3DMATERIAL9, Power), "MT_POWER"}
1422  };
1423 
1424  switch (op)
1425  {
1426  case MT_POWER:
1427  {
1428  float v = *(float *)value;
1429 
1430  TRACE("%s %.8e.\n", material_tbl[op].name, v);
1431  material->Power = v;
1432  break;
1433  }
1434  case MT_DIFFUSE:
1435  case MT_AMBIENT:
1436  case MT_SPECULAR:
1437  case MT_EMISSIVE:
1438  {
1440 
1441  TRACE("%s, value (%.8e %.8e %.8e %.8e).\n", material_tbl[op].name, c.r, c.g, c.b, c.a);
1442  *(D3DCOLORVALUE *)((BYTE *)material + material_tbl[op].offset) = c;
1443  break;
1444  }
1445  default:
1446  WARN("Unknown material parameter %u.\n", op);
1447  break;
1448  }
1449 }
1450 
1452  struct d3dx_parameter *param, void *value_ptr)
1453 {
1454  static const struct
1455  {
1457  UINT elem_size;
1458  const char *name;
1459  }
1460  const_tbl[] =
1461  {
1462  {D3DXPT_FLOAT, sizeof(float) * 4, "SCT_VSFLOAT"},
1463  {D3DXPT_BOOL, sizeof(BOOL), "SCT_VSBOOL"},
1464  {D3DXPT_INT, sizeof(int) * 4, "SCT_VSINT"},
1465  {D3DXPT_FLOAT, sizeof(float) * 4, "SCT_PSFLOAT"},
1466  {D3DXPT_BOOL, sizeof(BOOL), "SCT_PSBOOL"},
1467  {D3DXPT_INT, sizeof(int) * 4, "SCT_PSINT"},
1468  };
1469 
1470  BOOL is_heap_buffer = FALSE;
1471  unsigned int element_count;
1472  void *buffer = value_ptr;
1474  HRESULT ret;
1475 
1476  assert(op < ARRAY_SIZE(const_tbl));
1477  element_count = param->bytes / const_tbl[op].elem_size;
1478  TRACE("%s, index %u, element_count %u.\n", const_tbl[op].name, index, element_count);
1479  if (param->type != const_tbl[op].type)
1480  {
1481  FIXME("Unexpected param type %u.\n", param->type);
1482  return D3DERR_INVALIDCALL;
1483  }
1484 
1485  if (param->bytes % const_tbl[op].elem_size || element_count > 1)
1486  {
1487  unsigned int param_data_size;
1488 
1489  TRACE("Parameter size %u, rows %u, cols %u.\n", param->bytes, param->rows, param->columns);
1490 
1491  if (param->bytes % const_tbl[op].elem_size)
1492  ++element_count;
1493  if (element_count > 1)
1494  {
1495  WARN("Setting %u elements.\n", element_count);
1496  buffer = HeapAlloc(GetProcessHeap(), 0, const_tbl[op].elem_size * element_count);
1497  if (!buffer)
1498  {
1499  ERR("Out of memory.\n");
1500  return E_OUTOFMEMORY;
1501  }
1502  is_heap_buffer = TRUE;
1503  }
1504  else
1505  {
1506  assert(const_tbl[op].elem_size <= sizeof(value));
1507  buffer = &value;
1508  }
1509  param_data_size = min(param->bytes, const_tbl[op].elem_size);
1510  memcpy(buffer, value_ptr, param_data_size);
1511  memset((unsigned char *)buffer + param_data_size, 0,
1512  const_tbl[op].elem_size * element_count - param_data_size);
1513  }
1514 
1515  switch (op)
1516  {
1517  case SCT_VSFLOAT:
1518  ret = SET_D3D_STATE(effect, SetVertexShaderConstantF, index, (const float *)buffer, element_count);
1519  break;
1520  case SCT_VSBOOL:
1521  ret = SET_D3D_STATE(effect, SetVertexShaderConstantB, index, (const BOOL *)buffer, element_count);
1522  break;
1523  case SCT_VSINT:
1524  ret = SET_D3D_STATE(effect, SetVertexShaderConstantI, index, (const int *)buffer, element_count);
1525  break;
1526  case SCT_PSFLOAT:
1527  ret = SET_D3D_STATE(effect, SetPixelShaderConstantF, index, (const float *)buffer, element_count);
1528  break;
1529  case SCT_PSBOOL:
1530  ret = SET_D3D_STATE(effect, SetPixelShaderConstantB, index, (const BOOL *)buffer, element_count);
1531  break;
1532  case SCT_PSINT:
1533  ret = SET_D3D_STATE(effect, SetPixelShaderConstantI, index, (const int *)buffer, element_count);
1534  break;
1535  default:
1537  break;
1538  }
1539 
1540  if (is_heap_buffer)
1542 
1543  return ret;
1544 }
1545 
1546 static HRESULT d3dx9_apply_state(struct d3dx_effect *effect, struct d3dx_pass *pass,
1547  struct d3dx_state *state, unsigned int parent_index, BOOL update_all);
1548 
1550  struct d3dx_parameter *param, BOOL vs, BOOL update_all)
1551 {
1552  HRESULT hr, ret;
1553  struct d3dx_parameter **params;
1554  D3DXCONSTANT_DESC *cdesc;
1555  unsigned int parameters_count;
1556  unsigned int i, j;
1557 
1558  if (!param->param_eval)
1559  {
1560  FIXME("param_eval structure is null.\n");
1561  return D3DERR_INVALIDCALL;
1562  }
1564  param->param_eval, update_all)))
1565  return hr;
1566  params = param->param_eval->shader_inputs.inputs_param;
1567  cdesc = param->param_eval->shader_inputs.inputs;
1568  parameters_count = param->param_eval->shader_inputs.input_count;
1569  ret = D3D_OK;
1570  for (i = 0; i < parameters_count; ++i)
1571  {
1572  if (params[i] && params[i]->class == D3DXPC_OBJECT && is_param_type_sampler(params[i]->type))
1573  {
1574  struct d3dx_sampler *sampler;
1575  unsigned int sampler_idx;
1576 
1577  for (sampler_idx = 0; sampler_idx < cdesc[i].RegisterCount; ++sampler_idx)
1578  {
1579  sampler = params[i]->element_count ? params[i]->members[sampler_idx].data : params[i]->data;
1580  TRACE("sampler %s, register index %u, state count %u.\n", debugstr_a(params[i]->name),
1581  cdesc[i].RegisterIndex, sampler->state_count);
1582  for (j = 0; j < sampler->state_count; ++j)
1583  {
1584  if (FAILED(hr = d3dx9_apply_state(effect, pass, &sampler->states[j],
1585  cdesc[i].RegisterIndex + sampler_idx + (vs ? D3DVERTEXTEXTURESAMPLER0 : 0),
1586  update_all)))
1587  ret = hr;
1588  }
1589  }
1590  }
1591  }
1592  return ret;
1593 }
1594 
1595 static HRESULT d3dx9_apply_state(struct d3dx_effect *effect, struct d3dx_pass *pass,
1596  struct d3dx_state *state, unsigned int parent_index, BOOL update_all)
1597 {
1598  struct d3dx_parameter *param;
1599  void *param_value;
1600  BOOL param_dirty;
1601  HRESULT hr;
1602 
1603  TRACE("operation %u, index %u, type %u.\n", state->operation, state->index, state->type);
1604 
1605  if (FAILED(hr = d3dx9_get_param_value_ptr(pass, state, &param_value, &param,
1606  update_all, &param_dirty)))
1607  {
1608  if (!update_all && hr == E_FAIL)
1609  {
1610  /* Native d3dx9 returns D3D_OK from CommitChanges() involving
1611  * out of bounds array access and does not touch the affected
1612  * states. */
1613  WARN("Returning D3D_OK on out of bounds array access.\n");
1614  return D3D_OK;
1615  }
1616  return hr;
1617  }
1618 
1619  if (!(update_all || param_dirty
1620  || state_table[state->operation].class == SC_VERTEXSHADER
1621  || state_table[state->operation].class == SC_PIXELSHADER
1622  || state_table[state->operation].class == SC_SETSAMPLER))
1623  return D3D_OK;
1624 
1625  switch (state_table[state->operation].class)
1626  {
1627  case SC_RENDERSTATE:
1628  TRACE("%s, operation %u, value %u.\n", state_table[state->operation].name,
1629  state_table[state->operation].op, *(DWORD *)param_value);
1630  return SET_D3D_STATE(effect, SetRenderState, state_table[state->operation].op, *(DWORD *)param_value);
1631  case SC_FVF:
1632  TRACE("%s, value %#x.\n", state_table[state->operation].name, *(DWORD *)param_value);
1633  return SET_D3D_STATE(effect, SetFVF, *(DWORD *)param_value);
1634  case SC_TEXTURE:
1635  {
1636  UINT unit;
1637 
1638  unit = parent_index == ~0u ? state->index : parent_index;
1639  TRACE("%s, unit %u, value %p.\n", state_table[state->operation].name, unit,
1640  *(IDirect3DBaseTexture9 **)param_value);
1641  return SET_D3D_STATE(effect, SetTexture, unit, *(IDirect3DBaseTexture9 **)param_value);
1642  }
1643  case SC_TEXTURESTAGE:
1644  TRACE("%s, stage %u, value %u.\n", state_table[state->operation].name, state->index, *(DWORD *)param_value);
1645  return SET_D3D_STATE(effect, SetTextureStageState, state->index,
1646  state_table[state->operation].op, *(DWORD *)param_value);
1647  case SC_SETSAMPLER:
1648  {
1649  struct d3dx_sampler *sampler;
1650  HRESULT ret, hr;
1651  unsigned int i;
1652 
1653  sampler = (struct d3dx_sampler *)param_value;
1654  TRACE("%s, sampler %u, applying %u states.\n", state_table[state->operation].name, state->index,
1655  sampler->state_count);
1656  ret = D3D_OK;
1657  for (i = 0; i < sampler->state_count; i++)
1658  {
1659  if (FAILED(hr = d3dx9_apply_state(effect, pass, &sampler->states[i], state->index, update_all)))
1660  ret = hr;
1661  }
1662  return ret;
1663  }
1664  case SC_SAMPLERSTATE:
1665  {
1666  UINT sampler;
1667 
1668  sampler = parent_index == ~0u ? state->index : parent_index;
1669  TRACE("%s, sampler %u, value %u.\n", state_table[state->operation].name, sampler, *(DWORD *)param_value);
1670  return SET_D3D_STATE(effect, SetSamplerState, sampler, state_table[state->operation].op,
1671  *(DWORD *)param_value);
1672  }
1673  case SC_VERTEXSHADER:
1674  TRACE("%s, shader %p.\n", state_table[state->operation].name, *(IDirect3DVertexShader9 **)param_value);
1675  if ((update_all || param_dirty)
1676  && FAILED(hr = SET_D3D_STATE(effect, SetVertexShader,
1677  *(IDirect3DVertexShader9 **)param_value)))
1678  ERR("Could not set vertex shader, hr %#x.\n", hr);
1679  else if (*(IDirect3DVertexShader9 **)param_value)
1680  hr = d3dx_set_shader_constants(effect, pass, param, TRUE, update_all || param_dirty);
1681  return hr;
1682  case SC_PIXELSHADER:
1683  TRACE("%s, shader %p.\n", state_table[state->operation].name, *(IDirect3DPixelShader9 **)param_value);
1684  if ((update_all || param_dirty)
1685  && FAILED(hr = SET_D3D_STATE(effect, SetPixelShader,
1686  *(IDirect3DPixelShader9 **)param_value)))
1687  ERR("Could not set pixel shader, hr %#x.\n", hr);
1688  else if (*(IDirect3DPixelShader9 **)param_value)
1689  hr = d3dx_set_shader_constants(effect, pass, param, FALSE, update_all || param_dirty);
1690  return hr;
1691  case SC_TRANSFORM:
1692  TRACE("%s, state %u.\n", state_table[state->operation].name, state->index);
1693  return SET_D3D_STATE(effect, SetTransform, state_table[state->operation].op + state->index,
1694  (D3DMATRIX *)param_value);
1695  case SC_LIGHTENABLE:
1696  TRACE("%s, index %u, value %u.\n", state_table[state->operation].name, state->index, *(BOOL *)param_value);
1697  return SET_D3D_STATE(effect, LightEnable, state->index, *(BOOL *)param_value);
1698  case SC_LIGHT:
1699  {
1700  TRACE("%s, index %u, op %u.\n", state_table[state->operation].name, state->index,
1701  state_table[state->operation].op);
1703  &effect->current_light[state->index], param_value);
1704  effect->light_updated |= 1u << state->index;
1705  return D3D_OK;
1706  }
1707  case SC_MATERIAL:
1708  {
1709  TRACE("%s, index %u, op %u.\n", state_table[state->operation].name, state->index,
1710  state_table[state->operation].op);
1712  &effect->current_material, param_value);
1713  effect->material_updated = TRUE;
1714  return D3D_OK;
1715  }
1716  case SC_NPATCHMODE:
1717  TRACE("%s, nsegments %f.\n", state_table[state->operation].name, *(float *)param_value);
1718  return SET_D3D_STATE(effect, SetNPatchMode, *(float *)param_value);
1719  case SC_SHADERCONST:
1720  TRACE("%s, index %u, op %u.\n", state_table[state->operation].name, state->index,
1721  state_table[state->operation].op);
1722  return d3dx_set_shader_const_state(effect, state_table[state->operation].op, state->index,
1723  param, param_value);
1724  default:
1725  FIXME("%s not handled.\n", state_table[state->operation].name);
1726  break;
1727  }
1728  return D3D_OK;
1729 }
1730 
1731 static HRESULT d3dx9_apply_pass_states(struct d3dx_effect *effect, struct d3dx_pass *pass, BOOL update_all)
1732 {
1733  unsigned int i;
1734  HRESULT ret;
1735  HRESULT hr;
1736  ULONG64 new_update_version = next_effect_update_version(effect);
1737 
1738  TRACE("effect %p, pass %p, state_count %u.\n", effect, pass, pass->state_count);
1739 
1740  ret = D3D_OK;
1741  for (i = 0; i < pass->state_count; ++i)
1742  {
1743  if (FAILED(hr = d3dx9_apply_state(effect, pass, &pass->states[i], ~0u, update_all)))
1744  {
1745  WARN("Error applying state, hr %#x.\n", hr);
1746  ret = hr;
1747  }
1748  }
1749 
1750  if (effect->light_updated)
1751  {
1752  for (i = 0; i < ARRAY_SIZE(effect->current_light); ++i)
1753  {
1754  if ((effect->light_updated & (1u << i))
1755  && FAILED(hr = SET_D3D_STATE(effect, SetLight, i, &effect->current_light[i])))
1756  {
1757  WARN("Error setting light, hr %#x.\n", hr);
1758  ret = hr;
1759  }
1760  }
1761  effect->light_updated = 0;
1762  }
1763 
1764  if (effect->material_updated
1765  && FAILED(hr = SET_D3D_STATE(effect, SetMaterial, &effect->current_material)))
1766  {
1767  WARN("Error setting material, hr %#x.\n", hr);
1768  ret = hr;
1769  }
1770  effect->material_updated = FALSE;
1771 
1772  pass->update_version = new_update_version;
1773  return ret;
1774 }
1775 
1776 static void param_set_data_pointer(struct d3dx_parameter *param, unsigned char *data, BOOL child, BOOL free_data)
1777 {
1778  unsigned char *member_data = data;
1779  unsigned int i, count;
1780 
1781  count = param->element_count ? param->element_count : param->member_count;
1782  for (i = 0; i < count; ++i)
1783  {
1784  param_set_data_pointer(&param->members[i], member_data, TRUE, free_data);
1785  if (data)
1786  member_data += param->members[i].bytes;
1787  }
1788  if (free_data)
1790  param->data = data;
1791 }
1792 
1793 static BOOL is_same_parameter(void *param1_, struct d3dx_parameter *param2)
1794 {
1795  struct d3dx_parameter *param1 = (struct d3dx_parameter *)param1_;
1796  BOOL matches;
1797  unsigned int i, member_count;
1798 
1799  matches = !strcmp(param1->name, param2->name) && param1->class == param2->class
1800  && param1->type == param2->type && param1->rows == param2->rows
1801  && param1->columns == param2->columns && param1->element_count == param2->element_count
1802  && param1->member_count == param2->member_count;
1803 
1804  member_count = param1->element_count ? param1->element_count : param1->member_count;
1805 
1806  if (!matches || !member_count)
1807  return matches;
1808 
1809  for (i = 0; i < member_count; ++i)
1810  {
1811  if (!is_same_parameter(&param1->members[i], &param2->members[i]))
1812  return FALSE;
1813  }
1814  return TRUE;
1815 }
1816 
1818 {
1819  unsigned int i, free_entry_index;
1820  unsigned int new_size, new_count;
1821 
1822  if (!(param->param.flags & PARAMETER_FLAG_SHARED) || !pool || is_param_type_sampler(param->param.type))
1823  return D3D_OK;
1824 
1825  free_entry_index = pool->size;
1826  for (i = 0; i < pool->size; ++i)
1827  {
1828  if (!pool->shared_data[i].count)
1829  free_entry_index = i;
1830  else if (is_same_parameter(&param->param, &pool->shared_data[i].parameters[0]->param))
1831  break;
1832  }
1833  if (i == pool->size)
1834  {
1835  i = free_entry_index;
1836  if (i == pool->size)
1837  {
1838  struct d3dx_shared_data *new_alloc;
1839 
1840  if (!pool->size)
1841  {
1842  new_size = INITIAL_POOL_SIZE;
1843  new_alloc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1844  sizeof(*pool->shared_data) * new_size);
1845  if (!new_alloc)
1846  {
1847  ERR("Out of memory.\n");
1848  return E_OUTOFMEMORY;
1849  }
1850  }
1851  else
1852  {
1853  new_size = pool->size * 2;
1854  new_alloc = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pool->shared_data,
1855  sizeof(*pool->shared_data) * new_size);
1856  if (!new_alloc)
1857  {
1858  ERR("Out of memory.\n");
1859  return E_OUTOFMEMORY;
1860  }
1861  if (new_alloc != pool->shared_data)
1862  {
1863  unsigned int j, k;
1864 
1865  for (j = 0; j < pool->size; ++j)
1866  for (k = 0; k < new_alloc[j].count; ++k)
1867  new_alloc[j].parameters[k]->shared_data = &new_alloc[j];
1868  }
1869  }
1870  pool->shared_data = new_alloc;
1871  pool->size = new_size;
1872  }
1873  pool->shared_data[i].data = param->param.data;
1874  }
1875  else
1876  {
1877  param_set_data_pointer(&param->param, pool->shared_data[i].data, FALSE, TRUE);
1878  }
1879  new_count = ++pool->shared_data[i].count;
1880  if (new_count >= pool->shared_data[i].size)
1881  {
1882  if (!pool->shared_data[i].size)
1883  {
1884  new_size = INITIAL_SHARED_DATA_SIZE;
1885  pool->shared_data[i].parameters = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1886  sizeof(*pool->shared_data[i].parameters) * INITIAL_SHARED_DATA_SIZE);
1887  }
1888  else
1889  {
1890  new_size = pool->shared_data[i].size * 2;
1891  pool->shared_data[i].parameters = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1892  pool->shared_data[i].parameters,
1893  sizeof(*pool->shared_data[i].parameters) * new_size);
1894  }
1895  pool->shared_data[i].size = new_size;
1896  }
1897 
1898  param->shared_data = &pool->shared_data[i];
1899  pool->shared_data[i].parameters[new_count - 1] = param;
1900 
1901  TRACE("name %s, parameter idx %u, new refcount %u.\n", debugstr_a(param->param.name), i,
1902  new_count);
1903 
1904  return D3D_OK;
1905 }
1906 
1908 {
1909  param->data = NULL;
1910  return FALSE;
1911 }
1912 
1914 {
1915  unsigned int new_count;
1916 
1917  if (!(param->param.flags & PARAMETER_FLAG_SHARED) || !param->shared_data)
1918  return;
1919  new_count = --param->shared_data->count;
1920 
1921  TRACE("param %p, param->shared_data %p, new_count %d.\n", param, param->shared_data, new_count);
1922 
1923  if (new_count)
1924  {
1925  unsigned int i;
1926 
1927  for (i = 0; i < new_count; ++i)
1928  {
1929  if (param->shared_data->parameters[i] == param)
1930  {
1931  memmove(&param->shared_data->parameters[i],
1932  &param->shared_data->parameters[i + 1],
1933  sizeof(param->shared_data->parameters[i]) * (new_count - i));
1934  break;
1935  }
1936  }
1938  }
1939  else
1940  {
1941  HeapFree(GetProcessHeap(), 0, param->shared_data->parameters);
1942  /* Zeroing table size is required as the entry in pool parameters table can be reused. */
1943  param->shared_data->size = 0;
1944  param->shared_data = NULL;
1945  }
1946 }
1947 
1948 static inline struct d3dx_effect_pool *impl_from_ID3DXEffectPool(ID3DXEffectPool *iface)
1949 {
1951 }
1952 
1953 static inline struct d3dx_effect_pool *unsafe_impl_from_ID3DXEffectPool(ID3DXEffectPool *iface);
1954 
1955 static inline struct d3dx_effect *impl_from_ID3DXEffect(ID3DXEffect *iface)
1956 {
1957  return CONTAINING_RECORD(iface, struct d3dx_effect, ID3DXEffect_iface);
1958 }
1959 
1960 /*** IUnknown methods ***/
1961 static HRESULT WINAPI d3dx_effect_QueryInterface(ID3DXEffect *iface, REFIID riid, void **object)
1962 {
1963  TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), object);
1964 
1965  if (IsEqualGUID(riid, &IID_IUnknown) ||
1966  IsEqualGUID(riid, &IID_ID3DXEffect))
1967  {
1968  iface->lpVtbl->AddRef(iface);
1969  *object = iface;
1970  return S_OK;
1971  }
1972 
1973  ERR("Interface %s not found\n", debugstr_guid(riid));
1974 
1975  return E_NOINTERFACE;
1976 }
1977 
1978 static ULONG WINAPI d3dx_effect_AddRef(ID3DXEffect *iface)
1979 {
1980  struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
1981 
1982  TRACE("(%p)->(): AddRef from %u\n", This, This->ref);
1983 
1984  return InterlockedIncrement(&This->ref);
1985 }
1986 
1987 static ULONG WINAPI d3dx_effect_Release(ID3DXEffect *iface)
1988 {
1989  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
1990  ULONG refcount = InterlockedDecrement(&effect->ref);
1991 
1992  TRACE("%p decreasing refcount to %u.\n", effect, refcount);
1993 
1994  if (!refcount)
1995  d3dx_effect_cleanup(effect);
1996 
1997  return refcount;
1998 }
1999 
2000 /*** ID3DXBaseEffect methods ***/
2002 {
2003  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2004 
2005  FIXME("iface %p, desc %p partial stub.\n", iface, desc);
2006 
2007  if (!desc)
2008  {
2009  WARN("Invalid argument specified.\n");
2010  return D3DERR_INVALIDCALL;
2011  }
2012 
2013  /* TODO: add creator and function count. */
2014  desc->Creator = NULL;
2015  desc->Functions = 0;
2016  desc->Parameters = effect->parameter_count;
2017  desc->Techniques = effect->technique_count;
2018 
2019  return D3D_OK;
2020 }
2021 
2022 static HRESULT WINAPI d3dx_effect_GetParameterDesc(ID3DXEffect *iface, D3DXHANDLE parameter,
2024 {
2025  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2026  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2027 
2028  TRACE("iface %p, parameter %p, desc %p.\n", iface, parameter, desc);
2029 
2030  if (!desc || !param)
2031  {
2032  WARN("Invalid argument specified.\n");
2033  return D3DERR_INVALIDCALL;
2034  }
2035 
2036  desc->Name = param->name;
2037  desc->Semantic = param->semantic;
2038  desc->Class = param->class;
2039  desc->Type = param->type;
2040  desc->Rows = param->rows;
2041  desc->Columns = param->columns;
2042  desc->Elements = param->element_count;
2043  desc->Annotations = is_top_level_parameter(param)
2044  ? top_level_parameter_from_parameter(param)->annotation_count : 0;
2045  desc->StructMembers = param->member_count;
2046  desc->Flags = param->flags;
2047  desc->Bytes = param->bytes;
2048 
2049  return D3D_OK;
2050 }
2051 
2052 static HRESULT WINAPI d3dx_effect_GetTechniqueDesc(ID3DXEffect *iface, D3DXHANDLE technique,
2054 {
2055  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2056  struct d3dx_technique *tech = technique ? get_valid_technique(effect, technique) : &effect->techniques[0];
2057 
2058  TRACE("iface %p, technique %p, desc %p.\n", iface, technique, desc);
2059 
2060  if (!desc || !tech)
2061  {
2062  WARN("Invalid argument specified.\n");
2063  return D3DERR_INVALIDCALL;
2064  }
2065 
2066  desc->Name = tech->name;
2067  desc->Passes = tech->pass_count;
2068  desc->Annotations = tech->annotation_count;
2069 
2070  return D3D_OK;
2071 }
2072 
2073 static HRESULT WINAPI d3dx_effect_GetPassDesc(ID3DXEffect *iface, D3DXHANDLE pass_handle, D3DXPASS_DESC *desc)
2074 {
2075  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2076  struct d3dx_pass *pass = get_valid_pass(effect, pass_handle);
2077  unsigned int i;
2078 
2079  TRACE("iface %p, pass %p, desc %p.\n", iface, pass, desc);
2080 
2081  if (!desc || !pass)
2082  {
2083  WARN("Invalid argument specified.\n");
2084  return D3DERR_INVALIDCALL;
2085  }
2086 
2087  desc->Name = pass->name;
2088  desc->Annotations = pass->annotation_count;
2089 
2090  desc->pVertexShaderFunction = NULL;
2091  desc->pPixelShaderFunction = NULL;
2092 
2093  if (effect->flags & D3DXFX_NOT_CLONEABLE)
2094  return D3D_OK;
2095 
2096  for (i = 0; i < pass->state_count; ++i)
2097  {
2098  struct d3dx_state *state = &pass->states[i];
2099 
2100  if (state_table[state->operation].class == SC_VERTEXSHADER
2101  || state_table[state->operation].class == SC_PIXELSHADER)
2102  {
2103  struct d3dx_parameter *param;
2104  void *param_value;
2105  BOOL param_dirty;
2106  HRESULT hr;
2107  void *data;
2108 
2109  if (FAILED(hr = d3dx9_get_param_value_ptr(pass, &pass->states[i], &param_value, &param,
2110  FALSE, &param_dirty)))
2111  return hr;
2112 
2113  data = param->object_id ? effect->objects[param->object_id].data : NULL;
2114  if (state_table[state->operation].class == SC_VERTEXSHADER)
2115  desc->pVertexShaderFunction = data;
2116  else
2117  desc->pPixelShaderFunction = data;
2118  }
2119  }
2120 
2121  return D3D_OK;
2122 }
2123 
2126 {
2127  FIXME("iface %p, shader %p, desc %p stub.\n", iface, shader, desc);
2128 
2129  return E_NOTIMPL;
2130 }
2131 
2132 static D3DXHANDLE WINAPI d3dx_effect_GetParameter(ID3DXEffect *iface, D3DXHANDLE parameter, UINT index)
2133 {
2134  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2135  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2136 
2137  TRACE("iface %p, parameter %p, index %u.\n", iface, parameter, index);
2138 
2139  if (!parameter)
2140  {
2141  if (index < effect->parameter_count)
2142  {
2143  TRACE("Returning parameter %p.\n", &effect->parameters[index]);
2144  return get_parameter_handle(&effect->parameters[index].param);
2145  }
2146  }
2147  else
2148  {
2149  if (param && !param->element_count && index < param->member_count)
2150  {
2151  TRACE("Returning parameter %p.\n", &param->members[index]);
2152  return get_parameter_handle(&param->members[index]);
2153  }
2154  }
2155 
2156  WARN("Parameter not found.\n");
2157 
2158  return NULL;
2159 }
2160 
2161 static D3DXHANDLE WINAPI d3dx_effect_GetParameterByName(ID3DXEffect *iface, D3DXHANDLE parameter,
2162  const char *name)
2163 {
2164  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2165  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2167 
2168  TRACE("iface %p, parameter %p, name %s.\n", iface, parameter, debugstr_a(name));
2169 
2170  if (!name)
2171  {
2173  TRACE("Returning parameter %p.\n", handle);
2174  return handle;
2175  }
2176 
2178  TRACE("Returning parameter %p.\n", handle);
2179 
2180  return handle;
2181 }
2182 
2184  const char *semantic)
2185 {
2186  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2187  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2188  struct d3dx_parameter *temp_param;
2189  unsigned int i;
2190 
2191  TRACE("iface %p, parameter %p, semantic %s.\n", iface, parameter, debugstr_a(semantic));
2192 
2193  if (!parameter)
2194  {
2195  for (i = 0; i < effect->parameter_count; ++i)
2196  {
2197  temp_param = &effect->parameters[i].param;
2198 
2199  if (!temp_param->semantic)
2200  {
2201  if (!semantic)
2202  {
2203  TRACE("Returning parameter %p\n", temp_param);
2204  return get_parameter_handle(temp_param);
2205  }
2206  continue;
2207  }
2208 
2209  if (!stricmp(temp_param->semantic, semantic))
2210  {
2211  TRACE("Returning parameter %p\n", temp_param);
2212  return get_parameter_handle(temp_param);
2213  }
2214  }
2215  }
2216  else if (param)
2217  {
2218  for (i = 0; i < param->member_count; ++i)
2219  {
2220  temp_param = &param->members[i];
2221 
2222  if (!temp_param->semantic)
2223  {
2224  if (!semantic)
2225  {
2226  TRACE("Returning parameter %p\n", temp_param);
2227  return get_parameter_handle(temp_param);
2228  }
2229  continue;
2230  }
2231 
2232  if (!stricmp(temp_param->semantic, semantic))
2233  {
2234  TRACE("Returning parameter %p\n", temp_param);
2235  return get_parameter_handle(temp_param);
2236  }
2237  }
2238  }
2239 
2240  WARN("Parameter not found.\n");
2241 
2242  return NULL;
2243 }
2244 
2246 {
2247  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2248  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2249 
2250  TRACE("iface %p, parameter %p, index %u.\n", iface, parameter, index);
2251 
2252  if (!param)
2253  {
2254  if (index < effect->parameter_count)
2255  {
2256  TRACE("Returning parameter %p.\n", &effect->parameters[index]);
2257  return get_parameter_handle(&effect->parameters[index].param);
2258  }
2259  }
2260  else
2261  {
2263  {
2264  TRACE("Returning parameter %p.\n", &param->members[index]);
2265  return get_parameter_handle(&param->members[index]);
2266  }
2267  }
2268 
2269  WARN("Parameter not found.\n");
2270 
2271  return NULL;
2272 }
2273 
2275 {
2276  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2277 
2278  TRACE("iface %p, index %u.\n", iface, index);
2279 
2280  if (index >= effect->technique_count)
2281  {
2282  WARN("Invalid argument specified.\n");
2283  return NULL;
2284  }
2285 
2286  TRACE("Returning technique %p.\n", &effect->techniques[index]);
2287 
2288  return get_technique_handle(&effect->techniques[index]);
2289 }
2290 
2291 static D3DXHANDLE WINAPI d3dx_effect_GetTechniqueByName(ID3DXEffect *iface, const char *name)
2292 {
2293  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2294  struct d3dx_technique *tech = get_technique_by_name(effect, name);
2295 
2296  TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
2297 
2298  if (tech)
2299  {
2301  TRACE("Returning technique %p\n", t);
2302  return t;
2303  }
2304 
2305  WARN("Technique not found.\n");
2306 
2307  return NULL;
2308 }
2309 
2310 static D3DXHANDLE WINAPI d3dx_effect_GetPass(ID3DXEffect *iface, D3DXHANDLE technique, UINT index)
2311 {
2312  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2313  struct d3dx_technique *tech = get_valid_technique(effect, technique);
2314 
2315  TRACE("iface %p, technique %p, index %u.\n", iface, technique, index);
2316 
2317  if (tech && index < tech->pass_count)
2318  {
2319  TRACE("Returning pass %p\n", &tech->passes[index]);
2320  return get_pass_handle(&tech->passes[index]);
2321  }
2322 
2323  WARN("Pass not found.\n");
2324 
2325  return NULL;
2326 }
2327 
2328 static D3DXHANDLE WINAPI d3dx_effect_GetPassByName(ID3DXEffect *iface, D3DXHANDLE technique, const char *name)
2329 {
2330  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2331  struct d3dx_technique *tech = get_valid_technique(effect, technique);
2332 
2333  TRACE("iface %p, technique %p, name %s.\n", iface, technique, debugstr_a(name));
2334 
2335  if (tech && name)
2336  {
2337  unsigned int i;
2338 
2339  for (i = 0; i < tech->pass_count; ++i)
2340  {
2341  struct d3dx_pass *pass = &tech->passes[i];
2342 
2343  if (!strcmp(pass->name, name))
2344  {
2345  TRACE("Returning pass %p\n", pass);
2346  return get_pass_handle(pass);
2347  }
2348  }
2349  }
2350 
2351  WARN("Pass not found.\n");
2352 
2353  return NULL;
2354 }
2355 
2357 {
2358  FIXME("iface %p, index %u stub.\n", iface, index);
2359 
2360  return NULL;
2361 }
2362 
2363 static D3DXHANDLE WINAPI d3dx_effect_GetFunctionByName(ID3DXEffect *iface, const char *name)
2364 {
2365  FIXME("iface %p, name %s stub.\n", iface, debugstr_a(name));
2366 
2367  return NULL;
2368 }
2369 
2371 {
2372  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2373  struct d3dx_parameter *annotations = NULL;
2374  unsigned int annotation_count;
2375 
2376  TRACE("iface %p, object %p, index %u.\n", iface, object, index);
2377 
2378  annotation_count = get_annotation_from_object(effect, object, &annotations);
2379 
2380  if (index < annotation_count)
2381  {
2382  TRACE("Returning parameter %p\n", &annotations[index]);
2383  return get_parameter_handle(&annotations[index]);
2384  }
2385 
2386  WARN("Annotation not found.\n");
2387 
2388  return NULL;
2389 }
2390 
2392  const char *name)
2393 {
2394  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2395  struct d3dx_parameter *annotation = NULL;
2396  struct d3dx_parameter *annotations = NULL;
2397  unsigned int annotation_count;
2398 
2399  TRACE("iface %p, object %p, name %s.\n", iface, object, debugstr_a(name));
2400 
2401  if (!name)
2402  {
2403  WARN("Invalid argument specified\n");
2404  return NULL;
2405  }
2406 
2407  annotation_count = get_annotation_from_object(effect, object, &annotations);
2408 
2409  annotation = get_annotation_by_name(effect, annotation_count, annotations, name);
2410  if (annotation)
2411  {
2412  TRACE("Returning parameter %p\n", annotation);
2414  }
2415 
2416  WARN("Annotation not found.\n");
2417 
2418  return NULL;
2419 }
2420 
2421 static HRESULT WINAPI d3dx_effect_SetValue(ID3DXEffect *iface, D3DXHANDLE parameter,
2422  const void *data, UINT bytes)
2423 {
2424  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2425  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2426 
2427  TRACE("iface %p, parameter %p, data %p, bytes %u.\n", iface, parameter, data, bytes);
2428 
2429  if (!param)
2430  {
2431  WARN("Invalid parameter %p specified.\n", parameter);
2432  return D3DERR_INVALIDCALL;
2433  }
2434  if (param->class == D3DXPC_OBJECT && is_param_type_sampler(param->type))
2435  {
2436  WARN("Parameter is a sampler, returning E_FAIL.\n");
2437  return E_FAIL;
2438  }
2439 
2440  if (data && param->bytes <= bytes)
2441  return set_value(param, data, bytes, param_get_data_and_dirtify(effect, param, param->bytes, TRUE));
2442 
2443  WARN("Invalid argument specified.\n");
2444 
2445  return D3DERR_INVALIDCALL;
2446 }
2447 
2448 static HRESULT WINAPI d3dx_effect_GetValue(ID3DXEffect *iface, D3DXHANDLE parameter, void *data, UINT bytes)
2449 {
2450  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2451  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2452 
2453  TRACE("iface %p, parameter %p, data %p, bytes %u.\n", iface, parameter, data, bytes);
2454 
2455  if (!param)
2456  {
2457  WARN("Invalid parameter %p specified.\n", parameter);
2458  return D3DERR_INVALIDCALL;
2459  }
2460  if (param->class == D3DXPC_OBJECT && is_param_type_sampler(param->type))
2461  {
2462  WARN("Parameter is a sampler, returning E_FAIL.\n");
2463  return E_FAIL;
2464  }
2465 
2466  if (data && param->bytes <= bytes)
2467  {
2468  TRACE("Type %s.\n", debug_d3dxparameter_type(param->type));
2469 
2470  switch (param->type)
2471  {
2472  case D3DXPT_VOID:
2473  case D3DXPT_BOOL:
2474  case D3DXPT_INT:
2475  case D3DXPT_FLOAT:
2476  case D3DXPT_STRING:
2477  break;
2478 
2479  case D3DXPT_VERTEXSHADER:
2480  case D3DXPT_PIXELSHADER:
2481  case D3DXPT_TEXTURE:
2482  case D3DXPT_TEXTURE1D:
2483  case D3DXPT_TEXTURE2D:
2484  case D3DXPT_TEXTURE3D:
2485  case D3DXPT_TEXTURECUBE:
2486  {
2487  unsigned int i;
2488 
2489  for (i = 0; i < (param->element_count ? param->element_count : 1); ++i)
2490  {
2491  IUnknown *unk = ((IUnknown **)param->data)[i];
2492  if (unk)
2493  IUnknown_AddRef(unk);
2494  }
2495  break;
2496  }
2497 
2498  default:
2499  FIXME("Unhandled type %s.\n", debug_d3dxparameter_type(param->type));
2500  break;
2501  }
2502 
2503  TRACE("Copy %u bytes.\n", param->bytes);
2504  memcpy(data, param->data, param->bytes);
2505  return D3D_OK;
2506  }
2507 
2508  WARN("Parameter not found.\n");
2509 
2510  return D3DERR_INVALIDCALL;
2511 }
2512 
2513 static HRESULT WINAPI d3dx_effect_SetBool(ID3DXEffect *iface, D3DXHANDLE parameter, BOOL b)
2514 {
2515  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2516  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2517 
2518  TRACE("iface %p, parameter %p, b %#x.\n", iface, parameter, b);
2519 
2520  if (param && !param->element_count && param->rows == 1 && param->columns == 1)
2521  {
2522  set_number(param_get_data_and_dirtify(effect, param, sizeof(int), TRUE),
2523  param->type, &b, D3DXPT_BOOL);
2524  return D3D_OK;
2525  }
2526 
2527  WARN("Parameter not found.\n");
2528 
2529  return D3DERR_INVALIDCALL;
2530 }
2531 
2532 static HRESULT WINAPI d3dx_effect_GetBool(ID3DXEffect *iface, D3DXHANDLE parameter, BOOL *b)
2533 {
2534  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2535  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2536 
2537  TRACE("iface %p, parameter %p, b %p.\n", iface, parameter, b);
2538 
2539  if (b && param && !param->element_count && param->rows == 1 && param->columns == 1)
2540  {
2541  set_number(b, D3DXPT_BOOL, param->data, param->type);
2542  TRACE("Returning %s\n", *b ? "TRUE" : "FALSE");
2543  return D3D_OK;
2544  }
2545 
2546  WARN("Parameter not found.\n");
2547 
2548  return D3DERR_INVALIDCALL;
2549 }
2550 
2551 static HRESULT WINAPI d3dx_effect_SetBoolArray(ID3DXEffect *iface, D3DXHANDLE parameter, const BOOL *b, UINT count)
2552 {
2553  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2554  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2555  DWORD *data;
2556 
2557  TRACE("iface %p, parameter %p, b %p, count %u.\n", iface, parameter, b, count);
2558 
2559  if (param)
2560  {
2561  unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2562 
2563  TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2564 
2565  switch (param->class)
2566  {
2567  case D3DXPC_SCALAR:
2568  case D3DXPC_VECTOR:
2569  case D3DXPC_MATRIX_ROWS:
2570  data = param_get_data_and_dirtify(effect, param, size * sizeof(int), TRUE);
2571  for (i = 0; i < size; ++i)
2572  {
2573  /* don't crop the input, use D3DXPT_INT instead of D3DXPT_BOOL */
2574  set_number(data + i, param->type, &b[i], D3DXPT_INT);
2575  }
2576  return D3D_OK;
2577 
2578  case D3DXPC_OBJECT:
2579  case D3DXPC_STRUCT:
2580  break;
2581 
2582  default:
2583  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2584  break;
2585  }
2586  }
2587 
2588  WARN("Parameter not found.\n");
2589 
2590  return D3DERR_INVALIDCALL;
2591 }
2592 
2593 static HRESULT WINAPI d3dx_effect_GetBoolArray(ID3DXEffect *iface, D3DXHANDLE parameter, BOOL *b, UINT count)
2594 {
2595  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2596  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2597 
2598  TRACE("iface %p, parameter %p, b %p, count %u.\n", iface, parameter, b, count);
2599 
2600  if (b && param && (param->class == D3DXPC_SCALAR
2601  || param->class == D3DXPC_VECTOR
2602  || param->class == D3DXPC_MATRIX_ROWS
2603  || param->class == D3DXPC_MATRIX_COLUMNS))
2604  {
2605  unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2606 
2607  for (i = 0; i < size; ++i)
2608  {
2609  set_number(&b[i], D3DXPT_BOOL, (DWORD *)param->data + i, param->type);
2610  }
2611  return D3D_OK;
2612  }
2613 
2614  WARN("Parameter not found.\n");
2615 
2616  return D3DERR_INVALIDCALL;
2617 }
2618 
2619 static HRESULT WINAPI d3dx_effect_SetInt(ID3DXEffect *iface, D3DXHANDLE parameter, INT n)
2620 {
2621  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2622  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2623 
2624  TRACE("iface %p, parameter %p, n %d.\n", iface, parameter, n);
2625 
2626  if (param && !param->element_count)
2627  {
2628  if (param->rows == 1 && param->columns == 1)
2629  {
2630  DWORD value;
2631 
2632  set_number(&value, param->type, &n, D3DXPT_INT);
2633  *(DWORD *)param_get_data_and_dirtify(effect, param, sizeof(int),
2634  value != *(DWORD *)param->data) = value;
2635  return D3D_OK;
2636  }
2637 
2638  /* Split the value if parameter is a vector with dimension 3 or 4. */
2639  if (param->type == D3DXPT_FLOAT
2640  && ((param->class == D3DXPC_VECTOR && param->columns != 2)
2641  || (param->class == D3DXPC_MATRIX_ROWS && param->rows != 2 && param->columns == 1)))
2642  {
2643  float *data;
2644 
2645  TRACE("Vector fixup.\n");
2646 
2648  min(4, param->rows * param->columns) * sizeof(float), TRUE);
2649 
2650  data[0] = ((n & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE;
2651  data[1] = ((n & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE;
2652  data[2] = (n & 0xff) * INT_FLOAT_MULTI_INVERSE;
2653  if (param->rows * param->columns > 3)
2654  data[3] = ((n & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE;
2655 
2656  return D3D_OK;
2657  }
2658  }
2659 
2660  WARN("Parameter not found.\n");
2661 
2662  return D3DERR_INVALIDCALL;
2663 }
2664 
2665 static HRESULT WINAPI d3dx_effect_GetInt(ID3DXEffect *iface, D3DXHANDLE parameter, INT *n)
2666 {
2667  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2668  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2669 
2670  TRACE("iface %p, parameter %p, n %p.\n", iface, parameter, n);
2671 
2672  if (n && param && !param->element_count)
2673  {
2674  if (param->columns == 1 && param->rows == 1)
2675  {
2676  set_number(n, D3DXPT_INT, param->data, param->type);
2677  TRACE("Returning %d.\n", *n);
2678  return D3D_OK;
2679  }
2680 
2681  if (param->type == D3DXPT_FLOAT &&
2682  ((param->class == D3DXPC_VECTOR && param->columns != 2)
2683  || (param->class == D3DXPC_MATRIX_ROWS && param->rows != 2 && param->columns == 1)))
2684  {
2685  TRACE("Vector fixup.\n");
2686 
2687  *n = min(max(0.0f, *((float *)param->data + 2)), 1.0f) * INT_FLOAT_MULTI;
2688  *n += ((int)(min(max(0.0f, *((float *)param->data + 1)), 1.0f) * INT_FLOAT_MULTI)) << 8;
2689  *n += ((int)(min(max(0.0f, *((float *)param->data + 0)), 1.0f) * INT_FLOAT_MULTI)) << 16;
2690  if (param->columns * param->rows > 3)
2691  *n += ((int)(min(max(0.0f, *((float *)param->data + 3)), 1.0f) * INT_FLOAT_MULTI)) << 24;
2692 
2693  TRACE("Returning %d.\n", *n);
2694  return D3D_OK;
2695  }
2696  }
2697 
2698  WARN("Parameter not found.\n");
2699 
2700  return D3DERR_INVALIDCALL;
2701 }
2702 
2703 static HRESULT WINAPI d3dx_effect_SetIntArray(ID3DXEffect *iface, D3DXHANDLE parameter, const INT *n, UINT count)
2704 {
2705  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2706  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2707  DWORD *data;
2708 
2709  TRACE("iface %p, parameter %p, n %p, count %u.\n", iface, parameter, n, count);
2710 
2711  if (param)
2712  {
2713  unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2714 
2715  TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2716 
2717  switch (param->class)
2718  {
2719  case D3DXPC_SCALAR:
2720  case D3DXPC_VECTOR:
2721  case D3DXPC_MATRIX_ROWS:
2722  data = param_get_data_and_dirtify(effect, param, size * sizeof(int), TRUE);
2723  for (i = 0; i < size; ++i)
2724  set_number(data + i, param->type, &n[i], D3DXPT_INT);
2725  return D3D_OK;
2726 
2727  case D3DXPC_OBJECT:
2728  case D3DXPC_STRUCT:
2729  break;
2730 
2731  default:
2732  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2733  break;
2734  }
2735  }
2736 
2737  WARN("Parameter not found.\n");
2738 
2739  return D3DERR_INVALIDCALL;
2740 }
2741 
2742 static HRESULT WINAPI d3dx_effect_GetIntArray(ID3DXEffect *iface, D3DXHANDLE parameter, INT *n, UINT count)
2743 {
2744  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2745  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2746 
2747  TRACE("iface %p, parameter %p, n %p, count %u.\n", iface, parameter, n, count);
2748 
2749  if (n && param && (param->class == D3DXPC_SCALAR
2750  || param->class == D3DXPC_VECTOR
2751  || param->class == D3DXPC_MATRIX_ROWS
2752  || param->class == D3DXPC_MATRIX_COLUMNS))
2753  {
2754  unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2755 
2756  for (i = 0; i < size; ++i)
2757  set_number(&n[i], D3DXPT_INT, (DWORD *)param->data + i, param->type);
2758  return D3D_OK;
2759  }
2760 
2761  WARN("Parameter not found.\n");
2762 
2763  return D3DERR_INVALIDCALL;
2764 }
2765 
2766 static HRESULT WINAPI d3dx_effect_SetFloat(ID3DXEffect *iface, D3DXHANDLE parameter, float f)
2767 {
2768  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2769  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2770 
2771  TRACE("iface %p, parameter %p, f %.8e.\n", iface, parameter, f);
2772 
2773  if (param && !param->element_count && param->rows == 1 && param->columns == 1)
2774  {
2775  DWORD value;
2776 
2777  set_number(&value, param->type, &f, D3DXPT_FLOAT);
2778  *(DWORD *)param_get_data_and_dirtify(effect, param, sizeof(float),
2779  value != *(DWORD *)param->data) = value;
2780  return D3D_OK;
2781  }
2782 
2783  WARN("Parameter not found.\n");
2784 
2785  return D3DERR_INVALIDCALL;
2786 }
2787 
2788 static HRESULT WINAPI d3dx_effect_GetFloat(ID3DXEffect *iface, D3DXHANDLE parameter, float *f)
2789 {
2790  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2791  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2792 
2793  TRACE("iface %p, parameter %p, f %p.\n", iface, parameter, f);
2794 
2795  if (f && param && !param->element_count && param->columns == 1 && param->rows == 1)
2796  {
2797  set_number(f, D3DXPT_FLOAT, (DWORD *)param->data, param->type);
2798  TRACE("Returning %f.\n", *f);
2799  return D3D_OK;
2800  }
2801 
2802  WARN("Parameter not found.\n");
2803 
2804  return D3DERR_INVALIDCALL;
2805 }
2806 
2807 static HRESULT WINAPI d3dx_effect_SetFloatArray(ID3DXEffect *iface, D3DXHANDLE parameter,
2808  const float *f, UINT count)
2809 {
2810  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2811  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2812  DWORD *data;
2813 
2814  TRACE("iface %p, parameter %p, f %p, count %u.\n", iface, parameter, f, count);
2815 
2816  if (param)
2817  {
2818  unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2819 
2820  TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2821 
2822  switch (param->class)
2823  {
2824  case D3DXPC_SCALAR:
2825  case D3DXPC_VECTOR:
2826  case D3DXPC_MATRIX_ROWS:
2827  data = param_get_data_and_dirtify(effect, param, size * sizeof(float), TRUE);
2828  for (i = 0; i < size; ++i)
2829  set_number(data + i, param->type, &f[i], D3DXPT_FLOAT);
2830  return D3D_OK;
2831 
2832  case D3DXPC_OBJECT:
2833  case D3DXPC_STRUCT:
2834  break;
2835 
2836  default:
2837  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2838  break;
2839  }
2840  }
2841 
2842  WARN("Parameter not found.\n");
2843 
2844  return D3DERR_INVALIDCALL;
2845 }
2846 
2847 static HRESULT WINAPI d3dx_effect_GetFloatArray(ID3DXEffect *iface, D3DXHANDLE parameter, float *f, UINT count)
2848 {
2849  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2850  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2851 
2852  TRACE("iface %p, parameter %p, f %p, count %u.\n", iface, parameter, f, count);
2853 
2854  if (f && param && (param->class == D3DXPC_SCALAR
2855  || param->class == D3DXPC_VECTOR
2856  || param->class == D3DXPC_MATRIX_ROWS
2857  || param->class == D3DXPC_MATRIX_COLUMNS))
2858  {
2859  unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2860 
2861  for (i = 0; i < size; ++i)
2862  set_number(&f[i], D3DXPT_FLOAT, (DWORD *)param->data + i, param->type);
2863  return D3D_OK;
2864  }
2865 
2866  WARN("Parameter not found.\n");
2867 
2868  return D3DERR_INVALIDCALL;
2869 }
2870 
2871 static HRESULT WINAPI d3dx_effect_SetVector(ID3DXEffect *iface, D3DXHANDLE parameter, const D3DXVECTOR4 *vector)
2872 {
2873  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2874  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2875 
2876  TRACE("iface %p, parameter %p, vector %p.\n", iface, parameter, vector);
2877 
2878  if (param && !param->element_count)
2879  {
2880  TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2881 
2882  switch (param->class)
2883  {
2884  case D3DXPC_SCALAR:
2885  case D3DXPC_VECTOR:
2886  if (param->type == D3DXPT_INT && param->bytes == 4)
2887  {
2888  DWORD tmp;
2889 
2890  TRACE("INT fixup.\n");
2891  tmp = max(min(vector->z, 1.0f), 0.0f) * INT_FLOAT_MULTI;
2892  tmp += ((DWORD)(max(min(vector->y, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 8;
2893  tmp += ((DWORD)(max(min(vector->x, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 16;
2894  tmp += ((DWORD)(max(min(vector->w, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 24;
2895 
2896  *(int *)param_get_data_and_dirtify(effect, param, sizeof(int), TRUE) = tmp;
2897  return D3D_OK;
2898  }
2899  if (param->type == D3DXPT_FLOAT)
2900  {
2901  memcpy(param_get_data_and_dirtify(effect, param, param->columns * sizeof(float), TRUE),
2902  vector, param->columns * sizeof(float));
2903  return D3D_OK;
2904  }
2905 
2906  set_vector(param, vector, param_get_data_and_dirtify(effect, param, param->columns * sizeof(float), TRUE));
2907  return D3D_OK;
2908 
2909  case D3DXPC_MATRIX_ROWS:
2910  case D3DXPC_OBJECT:
2911  case D3DXPC_STRUCT:
2912  break;
2913 
2914  default:
2915  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2916  break;
2917  }
2918  }
2919 
2920  WARN("Parameter not found.\n");
2921 
2922  return D3DERR_INVALIDCALL;
2923 }
2924 
2925 static HRESULT WINAPI d3dx_effect_GetVector(ID3DXEffect *iface, D3DXHANDLE parameter, D3DXVECTOR4 *vector)
2926 {
2927  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2928  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2929 
2930  TRACE("iface %p, parameter %p, vector %p.\n", iface, parameter, vector);
2931 
2932  if (vector && param && !param->element_count)
2933  {
2934  TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2935 
2936  switch (param->class)
2937  {
2938  case D3DXPC_SCALAR:
2939  case D3DXPC_VECTOR:
2940  if (param->type == D3DXPT_INT && param->bytes == 4)
2941  {
2942  TRACE("INT fixup.\n");
2943  vector->x = (((*(int *)param->data) & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE;
2944  vector->y = (((*(int *)param->data) & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE;
2945  vector->z = ((*(int *)param->data) & 0xff) * INT_FLOAT_MULTI_INVERSE;
2946  vector->w = (((*(int *)param->data) & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE;
2947  return D3D_OK;
2948  }
2950  return D3D_OK;
2951 
2952  case D3DXPC_MATRIX_ROWS:
2953  case D3DXPC_OBJECT:
2954  case D3DXPC_STRUCT:
2955  break;
2956 
2957  default:
2958  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2959  break;
2960  }
2961  }
2962 
2963  WARN("Parameter not found.\n");
2964 
2965  return D3DERR_INVALIDCALL;
2966 }
2967 
2968 static HRESULT WINAPI d3dx_effect_SetVectorArray(ID3DXEffect *iface, D3DXHANDLE parameter,
2969  const D3DXVECTOR4 *vector, UINT count)
2970 {
2971  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2972  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2973 
2974  TRACE("iface %p, parameter %p, vector %p, count %u.\n", iface, parameter, vector, count);
2975 
2976  if (param && param->element_count && param->element_count >= count)
2977  {
2978  unsigned int i;
2979  BYTE *data;
2980 
2981  TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2982 
2983  switch (param->class)
2984  {
2985  case D3DXPC_VECTOR:
2986  data = param_get_data_and_dirtify(effect, param, count * param->columns * sizeof(float), TRUE);
2987 
2988  if (param->type == D3DXPT_FLOAT)
2989  {
2990  if (param->columns == 4)
2991  {
2992  memcpy(data, vector, count * 4 * sizeof(float));
2993  }
2994  else
2995  {
2996  for (i = 0; i < count; ++i)
2997  memcpy((float *)data + param->columns * i, vector + i,
2998  param->columns * sizeof(float));
2999  }
3000  return D3D_OK;
3001  }
3002 
3003  for (i = 0; i < count; ++i)
3004  set_vector(&param->members[i], &vector[i], data + i * param->columns * sizeof(float));
3005 
3006  return D3D_OK;
3007 
3008  case D3DXPC_SCALAR:
3009  case D3DXPC_MATRIX_ROWS:
3010  case D3DXPC_OBJECT:
3011  case D3DXPC_STRUCT:
3012  break;
3013 
3014  default:
3015  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3016  break;
3017  }
3018  }
3019 
3020  WARN("Parameter not found.\n");
3021 
3022  return D3DERR_INVALIDCALL;
3023 }
3024 
3025 static HRESULT WINAPI d3dx_effect_GetVectorArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3027 {
3028  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3029  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3030 
3031  TRACE("iface %p, parameter %p, vector %p, count %u.\n", iface, parameter, vector, count);
3032 
3033  if (!count)
3034  return D3D_OK;
3035 
3037  {
3038  unsigned int i;
3039 
3040  TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3041 
3042  switch (param->class)
3043  {
3044  case D3DXPC_VECTOR:
3045  for (i = 0; i < count; ++i)
3046  get_vector(&param->members[i], &vector[i]);
3047  return D3D_OK;
3048 
3049  case D3DXPC_SCALAR:
3050  case D3DXPC_MATRIX_ROWS:
3051  case D3DXPC_OBJECT:
3052  case D3DXPC_STRUCT:
3053  break;
3054 
3055  default:
3056  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3057  break;
3058  }
3059  }
3060 
3061  WARN("Parameter not found.\n");
3062 
3063  return D3DERR_INVALIDCALL;
3064 }
3065 
3066 static HRESULT WINAPI d3dx_effect_SetMatrix(ID3DXEffect *iface, D3DXHANDLE parameter, const D3DXMATRIX *matrix)
3067 {
3068  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3069  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3070 
3071  TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3072 
3073  if (param && !param->element_count)
3074  {
3075  TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3076 
3077  switch (param->class)
3078  {
3079  case D3DXPC_MATRIX_ROWS:
3081  param->rows * param->columns * sizeof(float), TRUE));
3082  return D3D_OK;
3083 
3084  case D3DXPC_SCALAR:
3085  case D3DXPC_VECTOR:
3086  case D3DXPC_OBJECT:
3087  case D3DXPC_STRUCT:
3088  break;
3089 
3090  default:
3091  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3092  break;
3093  }
3094  }
3095 
3096  WARN("Parameter not found.\n");
3097 
3098  return D3DERR_INVALIDCALL;
3099 }
3100 
3101 static HRESULT WINAPI d3dx_effect_GetMatrix(ID3DXEffect *iface, D3DXHANDLE parameter, D3DXMATRIX *matrix)
3102 {
3103  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3104  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3105 
3106  TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3107 
3108  if (matrix && param && !param->element_count)
3109  {
3110  TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3111 
3112  switch (param->class)
3113  {
3114  case D3DXPC_MATRIX_ROWS:
3116  return D3D_OK;
3117 
3118  case D3DXPC_SCALAR:
3119  case D3DXPC_VECTOR:
3120  case D3DXPC_OBJECT:
3121  case D3DXPC_STRUCT:
3122  break;
3123 
3124  default:
3125  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3126  break;
3127  }
3128  }
3129 
3130  WARN("Parameter not found.\n");
3131 
3132  return D3DERR_INVALIDCALL;
3133 }
3134 
3135 static HRESULT WINAPI d3dx_effect_SetMatrixArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3136  const D3DXMATRIX *matrix, UINT count)
3137 {
3138  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3139  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3140 
3141  TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3142 
3143  if (param && param->element_count >= count)
3144  {
3145  unsigned int i;
3146  BYTE *data;
3147 
3148  TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3149 
3150  switch (param->class)
3151  {
3152  case D3DXPC_MATRIX_ROWS:
3153  data = param_get_data_and_dirtify(effect, param, count * param->rows
3154  * param->columns * sizeof(float), TRUE);
3155 
3156  for (i = 0; i < count; ++i)
3157  set_matrix(&param->members[i], &matrix[i],
3158  data + i * param->rows * param->columns * sizeof(float));
3159 
3160  return D3D_OK;
3161 
3162  case D3DXPC_SCALAR:
3163  case D3DXPC_VECTOR:
3164  case D3DXPC_OBJECT:
3165  case D3DXPC_STRUCT:
3166  break;
3167 
3168  default:
3169  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3170  break;
3171  }
3172  }
3173 
3174  WARN("Parameter not found.\n");
3175 
3176  return D3DERR_INVALIDCALL;
3177 }
3178 
3179 static HRESULT WINAPI d3dx_effect_GetMatrixArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3181 {
3182  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3183  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3184 
3185  TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3186 
3187  if (!count)
3188  return D3D_OK;
3189 
3191  {
3192  unsigned int i;
3193 
3194  TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3195 
3196  switch (param->class)
3197  {
3198  case D3DXPC_MATRIX_ROWS:
3199  for (i = 0; i < count; ++i)
3200  get_matrix(&param->members[i], &matrix[i], FALSE);
3201  return D3D_OK;
3202 
3203  case D3DXPC_SCALAR:
3204  case D3DXPC_VECTOR:
3205  case D3DXPC_OBJECT:
3206  case D3DXPC_STRUCT:
3207  break;
3208 
3209  default:
3210  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3211  break;
3212  }
3213  }
3214 
3215  WARN("Parameter not found.\n");
3216 
3217  return D3DERR_INVALIDCALL;
3218 }
3219 
3220 static HRESULT WINAPI d3dx_effect_SetMatrixPointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3221  const D3DXMATRIX **matrix, UINT count)
3222 {
3223  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3224  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3225 
3226  TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3227 
3229  {
3230  unsigned int i;
3231  BYTE *data;
3232 
3233  switch (param->class)
3234  {
3235  case D3DXPC_MATRIX_ROWS:
3236  data = param_get_data_and_dirtify(effect, param, count * param->rows
3237  * param->columns * sizeof(float), TRUE);
3238 
3239  for (i = 0; i < count; ++i)
3240  set_matrix(&param->members[i], matrix[i], data + i * param->rows
3241  * param->columns * sizeof(float));
3242 
3243  return D3D_OK;
3244 
3245  case D3DXPC_SCALAR:
3246  case D3DXPC_VECTOR:
3247  case D3DXPC_OBJECT:
3248  break;
3249 
3250  default:
3251  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3252  break;
3253  }
3254  }
3255 
3256  WARN("Parameter not found.\n");
3257 
3258  return D3DERR_INVALIDCALL;
3259 }
3260 
3261 static HRESULT WINAPI d3dx_effect_GetMatrixPointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3263 {
3264  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3265  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3266 
3267  TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3268 
3269  if (!count)
3270  return D3D_OK;
3271 
3273  {
3274  unsigned int i;
3275 
3276  TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3277 
3278  switch (param->class)
3279  {
3280  case D3DXPC_MATRIX_ROWS:
3281  for (i = 0; i < count; ++i)
3282  get_matrix(&param->members[i], matrix[i], FALSE);
3283  return D3D_OK;
3284 
3285  case D3DXPC_SCALAR:
3286  case D3DXPC_VECTOR:
3287  case D3DXPC_OBJECT:
3288  break;
3289 
3290  default:
3291  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3292  break;
3293  }
3294  }
3295 
3296  WARN("Parameter not found.\n");
3297 
3298  return D3DERR_INVALIDCALL;
3299 }
3300 
3301 static HRESULT WINAPI d3dx_effect_SetMatrixTranspose(ID3DXEffect *iface, D3DXHANDLE parameter,
3302  const D3DXMATRIX *matrix)
3303 {
3304  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3305  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3306 
3307  TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3308 
3309  if (param && !param->element_count)
3310  {
3311  TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3312 
3313  switch (param->class)
3314  {
3315  case D3DXPC_MATRIX_ROWS:
3317  param->rows * param->columns * sizeof(float), TRUE));
3318  return D3D_OK;
3319 
3320  case D3DXPC_SCALAR:
3321  case D3DXPC_VECTOR:
3322  case D3DXPC_OBJECT:
3323  case D3DXPC_STRUCT:
3324  break;
3325 
3326  default:
3327  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3328  break;
3329  }
3330  }
3331 
3332  WARN("Parameter not found.\n");
3333 
3334  return D3DERR_INVALIDCALL;
3335 }
3336 
3337 static HRESULT WINAPI d3dx_effect_GetMatrixTranspose(ID3DXEffect *iface, D3DXHANDLE parameter,
3338  D3DXMATRIX *matrix)
3339 {
3340  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3341  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3342 
3343  TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3344 
3345  if (matrix && param && !param->element_count)
3346  {
3347  TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3348 
3349  switch (param->class)
3350  {
3351  case D3DXPC_SCALAR:
3352  case D3DXPC_VECTOR:
3354  return D3D_OK;
3355 
3356  case D3DXPC_MATRIX_ROWS:
3358  return D3D_OK;
3359 
3360  case D3DXPC_OBJECT:
3361  case D3DXPC_STRUCT:
3362  break;
3363 
3364  default:
3365  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3366  break;
3367  }
3368  }
3369 
3370  WARN("Parameter not found.\n");
3371 
3372  return D3DERR_INVALIDCALL;
3373 }
3374 
3375 static HRESULT WINAPI d3dx_effect_SetMatrixTransposeArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3376  const D3DXMATRIX *matrix, UINT count)
3377 {
3378  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3379  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3380 
3381  TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3382 
3383  if (param && param->element_count >= count)
3384  {
3385  unsigned int i;
3386  BYTE *data;
3387 
3388  TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3389 
3390  switch (param->class)
3391  {
3392  case D3DXPC_MATRIX_ROWS:
3393  data = param_get_data_and_dirtify(effect, param, count * param->rows
3394  * param->columns * sizeof(float), TRUE);
3395 
3396  for (i = 0; i < count; ++i)
3397  set_matrix_transpose(&param->members[i], &matrix[i], data
3398  + i * param->rows * param->columns * sizeof(float));
3399 
3400  return D3D_OK;
3401 
3402  case D3DXPC_SCALAR:
3403  case D3DXPC_VECTOR:
3404  case D3DXPC_OBJECT:
3405  case D3DXPC_STRUCT:
3406  break;
3407 
3408  default:
3409  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3410  break;
3411  }
3412  }
3413 
3414  WARN("Parameter not found.\n");
3415 
3416  return D3DERR_INVALIDCALL;
3417 }
3418 
3419 static HRESULT WINAPI d3dx_effect_GetMatrixTransposeArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3421 {
3422  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3423  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3424 
3425  TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3426 
3427  if (!count)
3428  return D3D_OK;
3429 
3431  {
3432  unsigned int i;
3433 
3434  TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3435 
3436  switch (param->class)
3437  {
3438  case D3DXPC_MATRIX_ROWS:
3439  for (i = 0; i < count; ++i)
3440  get_matrix(&param->members[i], &matrix[i], TRUE);
3441  return D3D_OK;
3442 
3443  case D3DXPC_SCALAR:
3444  case D3DXPC_VECTOR:
3445  case D3DXPC_OBJECT:
3446  case D3DXPC_STRUCT:
3447  break;
3448 
3449  default:
3450  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3451  break;
3452  }
3453  }
3454 
3455  WARN("Parameter not found.\n");
3456 
3457  return D3DERR_INVALIDCALL;
3458 }
3459 
3461  const D3DXMATRIX **matrix, UINT count)
3462 {
3463  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3464  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3465 
3466  TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3467 
3469  {
3470  unsigned int i;
3471  BYTE *data;
3472 
3473  switch (param->class)
3474  {
3475  case D3DXPC_MATRIX_ROWS:
3476  data = param_get_data_and_dirtify(effect, param, count * param->rows
3477  * param->columns * sizeof(float), TRUE);
3478 
3479  for (i = 0; i < count; ++i)
3480  set_matrix_transpose(&param->members[i], matrix[i], data
3481  + i * param->rows * param->columns * sizeof(float));
3482 
3483  return D3D_OK;
3484 
3485  case D3DXPC_SCALAR:
3486  case D3DXPC_VECTOR:
3487  case D3DXPC_OBJECT:
3488  break;
3489 
3490  default:
3491  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3492  break;
3493  }
3494  }
3495 
3496  WARN("Parameter not found.\n");
3497 
3498  return D3DERR_INVALIDCALL;
3499 }
3500 
3503 {
3504  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3505  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3506 
3507  TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3508 
3509  if (!count)
3510  return D3D_OK;
3511 
3513  {
3514  unsigned int i;
3515 
3516  TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3517 
3518  switch (param->class)
3519  {
3520  case D3DXPC_MATRIX_ROWS:
3521  for (i = 0; i < count; ++i)
3522  get_matrix(&param->members[i], matrix[i], TRUE);
3523  return D3D_OK;
3524 
3525  case D3DXPC_SCALAR:
3526  case D3DXPC_VECTOR:
3527  case D3DXPC_OBJECT:
3528  break;
3529 
3530  default:
3531  FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3532  break;
3533  }
3534  }
3535 
3536  WARN("Parameter not found.\n");
3537 
3538  return D3DERR_INVALIDCALL;
3539 }
3540 
3541 static HRESULT WINAPI d3dx_effect_SetString(ID3DXEffect *iface, D3DXHANDLE parameter, const char *string)
3542 {
3543  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3544  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3545 
3546  TRACE("iface %p, parameter %p, string %s.\n", iface, parameter, debugstr_a(string));
3547 
3548  if (param && param->type == D3DXPT_STRING)
3549  return set_string(param_get_data_and_dirtify(effect, param, sizeof(void *), TRUE), string);
3550 
3551  WARN("Parameter not found.\n");
3552 
3553  return D3DERR_INVALIDCALL;
3554 }
3555 
3556 static HRESULT WINAPI d3dx_effect_GetString(ID3DXEffect *iface, D3DXHANDLE parameter, const char **string)
3557 {
3558  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3559  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3560 
3561  TRACE("iface %p, parameter %p, string %p.\n", iface, parameter, string);
3562 
3563  if (string && param && !param->element_count && param->type == D3DXPT_STRING)
3564  {
3565  *string = *(const char **)param->data;
3566  TRACE("Returning %s.\n", debugstr_a(*string));
3567  return D3D_OK;
3568  }
3569 
3570  WARN("Parameter not found.\n");
3571 
3572  return D3DERR_INVALIDCALL;
3573 }
3574 
3575 static HRESULT WINAPI d3dx_effect_SetTexture(ID3DXEffect *iface, D3DXHANDLE parameter,
3576  IDirect3DBaseTexture9 *texture)
3577 {
3578  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3579  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3580 
3581  TRACE("iface %p, parameter %p, texture %p.\n", iface, parameter, texture);
3582 
3583  if (param && !param->element_count
3584  && (param->type == D3DXPT_TEXTURE || param->type == D3DXPT_TEXTURE1D
3585  || param->type == D3DXPT_TEXTURE2D || param->type == D3DXPT_TEXTURE3D
3586  || param->type == D3DXPT_TEXTURECUBE))
3587  {
3588  IDirect3DBaseTexture9 **data = param_get_data_and_dirtify(effect, param,
3589  sizeof(void *), texture != *(IDirect3DBaseTexture9 **)param->data);
3590  IDirect3DBaseTexture9 *old_texture = *data;
3591 
3592  *data = texture;
3593 
3594  if (texture == old_texture)
3595  return D3D_OK;
3596 
3597  if (texture)
3599  if (old_texture)
3600  IDirect3DBaseTexture9_Release(old_texture);
3601 
3602  return D3D_OK;
3603  }
3604 
3605  WARN("Parameter not found.\n");
3606 
3607  return D3DERR_INVALIDCALL;
3608 }
3609 
3610 static HRESULT WINAPI d3dx_effect_GetTexture(ID3DXEffect *iface, D3DXHANDLE parameter,
3611  IDirect3DBaseTexture9 **texture)
3612 {
3613  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3614  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3615 
3616  TRACE("iface %p, parameter %p, texture %p.\n", iface, parameter, texture);
3617 
3618  if (texture && param && !param->element_count
3619  && (param->type == D3DXPT_TEXTURE || param->type == D3DXPT_TEXTURE1D
3620  || param->type == D3DXPT_TEXTURE2D || param->type == D3DXPT_TEXTURE3D
3621  || param->type == D3DXPT_TEXTURECUBE))
3622  {
3623  *texture = *(IDirect3DBaseTexture9 **)param->data;
3624  if (*texture)
3626  TRACE("Returning %p.\n", *texture);
3627  return D3D_OK;
3628  }
3629 
3630  WARN("Parameter not found.\n");
3631 
3632  return D3DERR_INVALIDCALL;
3633 }
3634 
3635 static HRESULT WINAPI d3dx_effect_GetPixelShader(ID3DXEffect *iface, D3DXHANDLE parameter,
3636  IDirect3DPixelShader9 **shader)
3637 {
3638  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3639  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3640 
3641  TRACE("iface %p, parameter %p, shader %p.\n", iface, parameter, shader);
3642 
3643  if (shader && param && !param->element_count && param->type == D3DXPT_PIXELSHADER)
3644  {
3645  if ((*shader = *(IDirect3DPixelShader9 **)param->data))
3647  TRACE("Returning %p.\n", *shader);
3648  return D3D_OK;
3649  }
3650 
3651  WARN("Parameter not found.\n");
3652 
3653  return D3DERR_INVALIDCALL;
3654 }
3655 
3656 static HRESULT WINAPI d3dx_effect_GetVertexShader(ID3DXEffect *iface, D3DXHANDLE parameter,
3657  IDirect3DVertexShader9 **shader)
3658 {
3659  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3660  struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3661 
3662  TRACE("iface %p, parameter %p, shader %p.\n", iface, parameter, shader);
3663 
3664  if (shader && param && !param->element_count && param->type == D3DXPT_VERTEXSHADER)
3665  {
3666  if ((*shader = *(IDirect3DVertexShader9 **)param->data))
3668  TRACE("Returning %p.\n", *shader);
3669  return D3D_OK;
3670  }
3671 
3672  WARN("Parameter not found.\n");
3673 
3674  return D3DERR_INVALIDCALL;
3675 }
3676 
3677 static HRESULT WINAPI d3dx_effect_SetArrayRange(ID3DXEffect *iface, D3DXHANDLE parameter, UINT start, UINT end)
3678 {
3679  FIXME("iface %p, parameter %p, start %u, end %u stub.\n", iface, parameter, start, end);
3680 
3681  return E_NOTIMPL;
3682 }
3683 
3684 /*** ID3DXEffect methods ***/
3685 static HRESULT WINAPI d3dx_effect_GetPool(ID3DXEffect *iface, ID3DXEffectPool **pool)
3686 {
3687  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3688 
3689  TRACE("iface %p, pool %p.\n", effect, pool);
3690 
3691  if (!pool)
3692  {
3693  WARN("Invalid argument supplied.\n");
3694  return D3DERR_INVALIDCALL;
3695  }
3696 
3697  *pool = NULL;
3698  if (effect->pool)
3699  {
3700  *pool = &effect->pool->ID3DXEffectPool_iface;
3701  (*pool)->lpVtbl->AddRef(*pool);
3702  }
3703 
3704  TRACE("Returning pool %p.\n", *pool);
3705 
3706  return S_OK;
3707 }
3708 
3709 static HRESULT WINAPI d3dx_effect_SetTechnique(ID3DXEffect *iface, D3DXHANDLE technique)
3710 {
3711  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3712  struct d3dx_technique *tech = get_valid_technique(effect, technique);
3713 
3714  TRACE("iface %p, technique %p\n", iface, technique);
3715 
3716  if (tech)
3717  {
3718  effect->active_technique = tech;
3719  TRACE("Technique %p\n", tech);
3720  return D3D_OK;
3721  }
3722 
3723  WARN("Technique not found.\n");
3724 
3725  return D3DERR_INVALIDCALL;
3726 }
3727 
3729 {
3730  struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
3731 
3732  TRACE("iface %p\n", This);
3733 
3734  return get_technique_handle(This->active_technique);
3735 }
3736 
3737 static HRESULT WINAPI d3dx_effect_ValidateTechnique(ID3DXEffect *iface, D3DXHANDLE technique)
3738 {
3739  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3740  struct d3dx_technique *tech = get_valid_technique(effect, technique);
3741  HRESULT ret = D3D_OK;
3742  unsigned int i, j;
3743 
3744  FIXME("iface %p, technique %p semi-stub.\n", iface, technique);
3745 
3746  if (!tech)
3747  {
3749  goto done;
3750  }
3751  for (i = 0; i < tech->pass_count; ++i)
3752  {
3753  struct d3dx_pass *pass = &tech->passes[i];
3754 
3755  for (j = 0; j < pass->state_count; ++j)
3756  {
3757  struct d3dx_state *state = &pass->states[j];
3758 
3759  if (state_table[state->operation].class == SC_VERTEXSHADER
3760  || state_table[state->operation].class == SC_PIXELSHADER)
3761  {
3762  struct d3dx_parameter *param;
3763  void *param_value;
3764  BOOL param_dirty;
3765  HRESULT hr;
3766 
3767  if (FAILED(hr = d3dx9_get_param_value_ptr(pass, &pass->states[j], &param_value, &param,
3768  FALSE, &param_dirty)))
3769  return hr;
3770 
3771  if (param->object_id && effect->objects[param->object_id].creation_failed)
3772  {
3773  ret = E_FAIL;
3774  goto done;
3775  }
3776  }
3777  }
3778  }
3779 done:
3780  TRACE("Returning %#x.\n", ret);
3781  return ret;
3782 }
3783 
3784 static HRESULT WINAPI d3dx_effect_FindNextValidTechnique(ID3DXEffect *iface, D3DXHANDLE technique,
3785  D3DXHANDLE *next_technique)
3786 {
3787  struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3788  struct d3dx_technique *prev_tech, *tech;
3789  unsigned int i;
3790 
3791  TRACE("iface %p, technique %p, next_technique %p.\n", iface, technique, next_technique);
3792 
3793  if (technique)
3794  {
3795  if (!(prev_tech = get_valid_technique(effect, technique)))
3796  return D3DERR_INVALIDCALL;
3797 
3798  for (i = 0; i < effect->technique_count; ++i)
3799  {
3800  tech = &effect->techniques[i];
3801  if (tech == prev_tech)
3802  {
3803  ++i;
3804  break;
3805  }
3806  }
3807  }
3808  else
3809  {
3810  i = 0;
3811  }
3812 
3813  for (; i < effect->technique_count; ++i)
3814  {
3815  tech = &effect->techniques[i];
3817  {
3818  *next_technique = get_technique_handle(tech);
3819  return D3D_OK;
3820  }
3821  }
3822 
3823  *next_technique = get_technique_handle(&effect->techniques[0]);
3824  return S_FALSE;
3825 }
3826 
3828  void *data);
3829 
3830 static BOOL walk_param_eval_dep(struct d3dx_param_eval *param_eval, walk_parameter_dep_func param_func,
3831  void *data)
3832 {
3833  struct d3dx_parameter **params;
3834  unsigned int i, param_count;
3835 
3836  if (!param_eval)
3837  return FALSE;
3838 
3839  params = param_eval->shader_inputs.inputs_param;
3840  param_count = param_eval->shader_inputs.input_count;
3841  for (i = 0; i < param_count; ++i)
3842  {
3843  if (walk_parameter_dep(params[i], param_func, data))
3844  return TRUE;
3845  }
3846 
3847  params = param_eval->pres.inputs.inputs_param;
3848  param_count = param_eval->pres.inputs.input_count;
3849  for (i = 0; i < param_count; ++i)
3850  {
3851  if (walk_parameter_dep(params[i], param_func, data))
3852  return TRUE;
3853  }
3854  return FALSE;
3855