ReactOS 0.4.15-dev-8231-g29a56f3
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
37static const char parameter_magic_string[4] = {'@', '!', '#', '\xFF'};
38static 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
134{
135 char *name;
138
141
143};
144
146{
147 char *name;
150
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
227static HRESULT d3dx_parse_state(struct d3dx_effect *effect, struct d3dx_state *state,
228 const char *data, const char **ptr, struct d3dx_object *objects);
230
232
233static const struct
234{
235 enum STATE_CLASS class;
237 const char *name;
238}
239state_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"},
435
436static inline void read_dword(const char **ptr, DWORD *d)
437{
438 memcpy(d, *ptr, sizeof(*d));
439 *ptr += sizeof(*d);
440}
441
442static 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
455static inline D3DXHANDLE get_parameter_handle(struct d3dx_parameter *parameter)
456{
457 return (D3DXHANDLE)parameter;
458}
459
460static inline D3DXHANDLE get_technique_handle(struct d3dx_technique *technique)
461{
462 return (D3DXHANDLE)technique;
463}
464
466{
467 return (D3DXHANDLE)pass;
468}
469
470static 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
485static 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
498static 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
516static 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
535static void free_state(struct d3dx_state *state)
536{
537 free_parameter(&state->parameter, FALSE, FALSE);
538}
539
540static void free_object(struct d3dx_object *object)
541{
542 HeapFree(GetProcessHeap(), 0, object->data);
543}
544
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
558static 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:
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:
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
658static 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
687static 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);
744}
745
746static 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
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
810static 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
836static 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
862static 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
876static 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
889static 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:
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{
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
982static 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
1213static 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
1281static 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
1318static 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
1330static 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)
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
1546static 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
1595static 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
1731static 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
1776static 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
1793static 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;
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
1948static inline struct d3dx_effect_pool *impl_from_ID3DXEffectPool(ID3DXEffectPool *iface)
1949{
1951}
1952
1953static inline struct d3dx_effect_pool *unsafe_impl_from_ID3DXEffectPool(ID3DXEffectPool *iface);
1954
1955static 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 ***/
1961static 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
1978static 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
1987static 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
2022static 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
2052static 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
2073static 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
2132static 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
2161static 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 {
2262 if (index < param->element_count)
2263 {
2264 TRACE("Returning parameter %p.\n", &param->members[index]);
2265 return get_parameter_handle(&param->members[index]);
2266 }
2267 }
2268
2269 WARN("Parameter not found.\n");
2270
2271 return NULL;
2272}
2273
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
2291static 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
2310static 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
2328static 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
2363static 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
2421static 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
2448static 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
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
2513static 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
2532static 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
2551static 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
2593static 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
2619static 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
2665static 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
2703static 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
2742static 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
2766static 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
2788static 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
2807static 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
2847static 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
2871static 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
2925static 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
2968static 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
3025static 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
3036 if (vector && param && count <= param->element_count)
3037 {
3038 unsigned int i;
3039
3040 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3041
3042 switch (param->class)
3043 {
3044 case D3DXPC_VECTOR:
3045 for (i = 0; i < count; ++i)
3046 get_vector(&param->members[i], &vector[i]);
3047 return D3D_OK;
3048
3049 case D3DXPC_SCALAR:
3050 case D3DXPC_MATRIX_ROWS:
3051 case D3DXPC_OBJECT:
3052 case D3DXPC_STRUCT:
3053 break;
3054
3055 default:
3056 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3057 break;
3058 }
3059 }
3060
3061 WARN("Parameter not found.\n");
3062
3063 return D3DERR_INVALIDCALL;
3064}
3065
3066static 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
3101static 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
3135static 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:
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
3179static 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
3190 if (matrix && param && count <= param->element_count)
3191 {
3192 unsigned int i;
3193
3194 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3195
3196 switch (param->class)
3197 {
3198 case D3DXPC_MATRIX_ROWS:
3199 for (i = 0; i < count; ++i)
3200 get_matrix(&param->members[i], &matrix[i], FALSE);
3201 return D3D_OK;
3202
3203 case D3DXPC_SCALAR:
3204 case D3DXPC_VECTOR:
3205 case D3DXPC_OBJECT:
3206 case D3DXPC_STRUCT:
3207 break;
3208
3209 default:
3210 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3211 break;
3212 }
3213 }
3214
3215 WARN("Parameter not found.\n");
3216
3217 return D3DERR_INVALIDCALL;
3218}
3219
3220static HRESULT WINAPI d3dx_effect_SetMatrixPointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3221 const D3DXMATRIX **matrix, UINT count)
3222{
3223 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3224 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3225
3226 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3227
3228 if (param && count <= param->element_count)
3229 {
3230 unsigned int i;
3231 BYTE *data;
3232
3233 switch (param->class)
3234 {
3235 case D3DXPC_MATRIX_ROWS:
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
3261static 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
3272 if (param && matrix && count <= param->element_count)
3273 {
3274 unsigned int i;
3275
3276 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3277
3278 switch (param->class)
3279 {
3280 case D3DXPC_MATRIX_ROWS:
3281 for (i = 0; i < count; ++i)
3282 get_matrix(&param->members[i], matrix[i], FALSE);
3283 return D3D_OK;
3284
3285 case D3DXPC_SCALAR:
3286 case D3DXPC_VECTOR:
3287 case D3DXPC_OBJECT:
3288 break;
3289
3290 default:
3291 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3292 break;
3293 }
3294 }
3295
3296 WARN("Parameter not found.\n");
3297
3298 return D3DERR_INVALIDCALL;
3299}
3300
3301static 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
3337static HRESULT WINAPI d3dx_effect_GetMatrixTranspose(ID3DXEffect *iface, D3DXHANDLE parameter,
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
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:
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
3421{
3422 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3423 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3424
3425 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3426
3427 if (!count)
3428 return D3D_OK;
3429
3430 if (matrix && param && count <= param->element_count)
3431 {
3432 unsigned int i;
3433
3434 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3435
3436 switch (param->class)
3437 {
3438 case D3DXPC_MATRIX_ROWS:
3439 for (i = 0; i < count; ++i)
3440 get_matrix(&param->members[i], &matrix[i], TRUE);
3441 return D3D_OK;
3442
3443 case D3DXPC_SCALAR:
3444 case D3DXPC_VECTOR:
3445 case D3DXPC_OBJECT:
3446 case D3DXPC_STRUCT:
3447 break;
3448
3449 default:
3450 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3451 break;
3452 }
3453 }
3454
3455 WARN("Parameter not found.\n");
3456
3457 return D3DERR_INVALIDCALL;
3458}
3459
3461 const D3DXMATRIX **matrix, UINT count)
3462{
3463 struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3464 struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3465
3466 TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3467
3468 if (param && count <= param->element_count)
3469 {
3470 unsigned int i;
3471 BYTE *data;
3472
3473 switch (param->class)
3474 {
3475 case D3DXPC_MATRIX_ROWS:
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
3512 if (matrix && param && count <= param->element_count)
3513 {
3514 unsigned int i;
3515
3516 TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3517
3518 switch (param->class)
3519 {
3520 case D3DXPC_MATRIX_ROWS:
3521 for (i = 0; i < count; ++i)
3522 get_matrix(&param->members[i], matrix[i], TRUE);
3523 return D3D_OK;
3524
3525 case D3DXPC_SCALAR:
3526 case D3DXPC_VECTOR:
3527 case D3DXPC_OBJECT:
3528 break;
3529
3530 default:
3531 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3532 break;
3533 }
3534 }
3535
3536 WARN("Parameter not found.\n");
3537
3538 return D3DERR_INVALIDCALL;
3539}
3540
3541static 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
3556static HRESULT WINAPI d3dx_effect_GetString(ID3DXEffect *iface, D3DXHANDLE parameter, const char **string)
3557{
3558