wined3d: Pack hardcoded local constants in ARB.
[wine] / dlls / d3d10 / effect.c
1 /*
2  * Copyright 2009 Henri Verbeet for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  *
18  */
19
20 #include "config.h"
21 #include "wine/port.h"
22
23 #include "d3d10_private.h"
24
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d10);
26
27 #define MAKE_TAG(ch0, ch1, ch2, ch3) \
28     ((DWORD)(ch0) | ((DWORD)(ch1) << 8) | \
29     ((DWORD)(ch2) << 16) | ((DWORD)(ch3) << 24 ))
30 #define TAG_DXBC MAKE_TAG('D', 'X', 'B', 'C')
31 #define TAG_FX10 MAKE_TAG('F', 'X', '1', '0')
32 #define TAG_ISGN MAKE_TAG('I', 'S', 'G', 'N')
33
34 static const struct ID3D10EffectTechniqueVtbl d3d10_effect_technique_vtbl;
35 static const struct ID3D10EffectPassVtbl d3d10_effect_pass_vtbl;
36
37 static inline void read_dword(const char **ptr, DWORD *d)
38 {
39     memcpy(d, *ptr, sizeof(*d));
40     *ptr += sizeof(*d);
41 }
42
43 static inline void skip_dword_unknown(const char **ptr, unsigned int count)
44 {
45     unsigned int i;
46     DWORD d;
47
48     FIXME("Skipping %u unknown DWORDs:\n", count);
49     for (i = 0; i < count; ++i)
50     {
51         read_dword(ptr, &d);
52         FIXME("\t0x%08x\n", d);
53     }
54 }
55
56 static inline void write_dword(char **ptr, DWORD d)
57 {
58     memcpy(*ptr, &d, sizeof(d));
59     *ptr += sizeof(d);
60 }
61
62 static inline void write_dword_unknown(char **ptr, DWORD d)
63 {
64     FIXME("Writing unknown DWORD 0x%08x\n", d);
65     write_dword(ptr, d);
66 }
67
68 static inline void read_tag(const char **ptr, DWORD *t, char t_str[5])
69 {
70     read_dword(ptr, t);
71     memcpy(t_str, t, 4);
72     t_str[4] = '\0';
73 }
74
75 static HRESULT parse_dxbc(const char *data, SIZE_T data_size,
76         HRESULT (*chunk_handler)(const char *data, DWORD data_size, DWORD tag, void *ctx), void *ctx)
77 {
78     const char *ptr = data;
79     HRESULT hr = S_OK;
80     DWORD chunk_count;
81     DWORD total_size;
82     char tag_str[5];
83     unsigned int i;
84     DWORD tag;
85
86     read_tag(&ptr, &tag, tag_str);
87     TRACE("tag: %s\n", tag_str);
88
89     if (tag != TAG_DXBC)
90     {
91         WARN("Wrong tag.\n");
92         return E_FAIL;
93     }
94
95     /* checksum? */
96     skip_dword_unknown(&ptr, 4);
97
98     skip_dword_unknown(&ptr, 1);
99
100     read_dword(&ptr, &total_size);
101     TRACE("total size: %#x\n", total_size);
102
103     read_dword(&ptr, &chunk_count);
104     TRACE("chunk count: %#x\n", chunk_count);
105
106     for (i = 0; i < chunk_count; ++i)
107     {
108         DWORD chunk_tag, chunk_size;
109         const char *chunk_ptr;
110         DWORD chunk_offset;
111
112         read_dword(&ptr, &chunk_offset);
113         TRACE("chunk %u at offset %#x\n", i, chunk_offset);
114
115         chunk_ptr = data + chunk_offset;
116
117         read_dword(&chunk_ptr, &chunk_tag);
118         read_dword(&chunk_ptr, &chunk_size);
119
120         hr = chunk_handler(chunk_ptr, chunk_size, chunk_tag, ctx);
121         if (FAILED(hr)) break;
122     }
123
124     return hr;
125 }
126
127 static HRESULT parse_fx10_pass_index(struct d3d10_effect_pass *p, const char **ptr)
128 {
129     unsigned int i;
130
131     read_dword(ptr, &p->start);
132     TRACE("Pass starts at offset %#x\n", p->start);
133
134     read_dword(ptr, &p->variable_count);
135     TRACE("Pass has %u variables\n", p->variable_count);
136
137     skip_dword_unknown(ptr, 1);
138
139     p->variables = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, p->variable_count * sizeof(*p->variables));
140     if (!p->variables)
141     {
142         ERR("Failed to allocate variables memory\n");
143         return E_OUTOFMEMORY;
144     }
145
146     for (i = 0; i < p->variable_count; ++i)
147     {
148         struct d3d10_effect_variable *v = &p->variables[i];
149
150         v->pass = p;
151
152         read_dword(ptr, &v->type);
153         TRACE("Variable %u is of type %#x\n", i, v->type);
154
155         skip_dword_unknown(ptr, 2);
156
157         read_dword(ptr, &v->idx_offset);
158         TRACE("Variable %u idx is at offset %#x\n", i, v->idx_offset);
159     }
160
161     return S_OK;
162 }
163
164 static HRESULT parse_fx10_technique_index(struct d3d10_effect_technique *t, const char **ptr)
165 {
166     HRESULT hr = S_OK;
167     unsigned int i;
168
169     read_dword(ptr, &t->start);
170     TRACE("Technique starts at offset %#x\n", t->start);
171
172     read_dword(ptr, &t->pass_count);
173     TRACE("Technique has %u passes\n", t->pass_count);
174
175     skip_dword_unknown(ptr, 1);
176
177     t->passes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, t->pass_count * sizeof(*t->passes));
178     if (!t->passes)
179     {
180         ERR("Failed to allocate passes memory\n");
181         return E_OUTOFMEMORY;
182     }
183
184     for (i = 0; i < t->pass_count; ++i)
185     {
186         struct d3d10_effect_pass *p = &t->passes[i];
187
188         p->vtbl = &d3d10_effect_pass_vtbl;
189         p->technique = t;
190
191         hr = parse_fx10_pass_index(p, ptr);
192         if (FAILED(hr)) break;
193     }
194
195     return hr;
196 }
197
198 static HRESULT shader_chunk_handler(const char *data, DWORD data_size, DWORD tag, void *ctx)
199 {
200     struct d3d10_effect_shader_variable *s = ctx;
201     char tag_str[5];
202
203     memcpy(tag_str, &tag, 4);
204     tag_str[4] = '\0';
205     TRACE("tag: %s\n", tag_str);
206
207     TRACE("chunk size: %#x\n", data_size);
208
209     switch(tag)
210     {
211         case TAG_ISGN:
212         {
213             /* 32 (DXBC header) + 1 * 4 (chunk index) + 2 * 4 (chunk header) + data_size (chunk data) */
214             UINT size = 44 + data_size;
215             char *ptr;
216
217             s->input_signature = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
218             if (!s->input_signature)
219             {
220                 ERR("Failed to allocate input signature data\n");
221                 return E_OUTOFMEMORY;
222             }
223             s->input_signature_size = size;
224
225             ptr = s->input_signature;
226
227             write_dword(&ptr, TAG_DXBC);
228
229             /* signature(?) */
230             write_dword_unknown(&ptr, 0);
231             write_dword_unknown(&ptr, 0);
232             write_dword_unknown(&ptr, 0);
233             write_dword_unknown(&ptr, 0);
234
235             /* seems to be always 1 */
236             write_dword_unknown(&ptr, 1);
237
238             /* DXBC size */
239             write_dword(&ptr, size);
240
241             /* chunk count */
242             write_dword(&ptr, 1);
243
244             /* chunk index */
245             write_dword(&ptr, (ptr - s->input_signature) + 4);
246
247             /* chunk */
248             write_dword(&ptr, TAG_ISGN);
249             write_dword(&ptr, data_size);
250             memcpy(ptr, data, data_size);
251             break;
252         }
253
254         default:
255             FIXME("Unhandled chunk %s\n", tag_str);
256             break;
257     }
258
259     return S_OK;
260 }
261
262 static HRESULT parse_shader(struct d3d10_effect_variable *v, const char *data)
263 {
264     ID3D10Device *device = v->pass->technique->effect->device;
265     struct d3d10_effect_shader_variable *s;
266     const char *ptr = data;
267     DWORD dxbc_size;
268     HRESULT hr;
269
270     v->data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct d3d10_effect_shader_variable));
271     if (!v->data)
272     {
273         ERR("Failed to allocate shader variable memory\n");
274         return E_OUTOFMEMORY;
275     }
276
277     if (!ptr) return S_OK;
278
279     s = v->data;
280
281     read_dword(&ptr, &dxbc_size);
282     TRACE("dxbc size: %#x\n", dxbc_size);
283
284     switch (v->type)
285     {
286         case D3D10_EVT_VERTEXSHADER:
287             hr = ID3D10Device_CreateVertexShader(device, ptr, dxbc_size, &s->shader.vs);
288             if (FAILED(hr)) return hr;
289             break;
290
291         case D3D10_EVT_PIXELSHADER:
292             hr = ID3D10Device_CreatePixelShader(device, ptr, dxbc_size, &s->shader.ps);
293             if (FAILED(hr)) return hr;
294             break;
295         case D3D10_EVT_GEOMETRYSHADER:
296             hr = ID3D10Device_CreateGeometryShader(device, ptr, dxbc_size, &s->shader.gs);
297             if (FAILED(hr)) return hr;
298             break;
299     }
300
301     return parse_dxbc(ptr, dxbc_size, shader_chunk_handler, s);
302 }
303
304 static HRESULT parse_fx10_variable(struct d3d10_effect_variable *v, const char *data)
305 {
306     const char *ptr;
307     DWORD offset;
308     HRESULT hr;
309
310     ptr = data + v->idx_offset;
311     read_dword(&ptr, &offset);
312
313     TRACE("Variable of type %#x starts at offset %#x\n", v->type, offset);
314
315     /* FIXME: This probably isn't completely correct. */
316     if (offset == 1)
317     {
318         WARN("Skipping variable\n");
319         ptr = NULL;
320     }
321     else
322     {
323         ptr = data + offset;
324     }
325
326     switch (v->type)
327     {
328         case D3D10_EVT_VERTEXSHADER:
329             TRACE("Vertex shader\n");
330             hr = parse_shader(v, ptr);
331             break;
332
333         case D3D10_EVT_PIXELSHADER:
334             TRACE("Pixel shader\n");
335             hr = parse_shader(v, ptr);
336             break;
337
338         case D3D10_EVT_GEOMETRYSHADER:
339             TRACE("Geometry shader\n");
340             hr = parse_shader(v, ptr);
341             break;
342
343         default:
344             FIXME("Unhandled variable type %#x\n", v->type);
345             hr = E_FAIL;
346             break;
347     }
348
349     return hr;
350 }
351
352 static HRESULT parse_fx10_pass(struct d3d10_effect_pass *p, const char *data)
353 {
354     HRESULT hr = S_OK;
355     const char *ptr;
356     size_t name_len;
357     unsigned int i;
358
359     ptr = data + p->start;
360
361     name_len = strlen(ptr) + 1;
362     p->name = HeapAlloc(GetProcessHeap(), 0, name_len);
363     if (!p->name)
364     {
365         ERR("Failed to allocate name memory\n");
366         return E_OUTOFMEMORY;
367     }
368
369     memcpy(p->name, ptr, name_len);
370     ptr += name_len;
371
372     TRACE("pass name: %s\n", p->name);
373
374     for (i = 0; i < p->variable_count; ++i)
375     {
376         hr = parse_fx10_variable(&p->variables[i], data);
377         if (FAILED(hr)) break;
378     }
379
380     return hr;
381 }
382
383 static HRESULT parse_fx10_technique(struct d3d10_effect_technique *t, const char *data)
384 {
385     HRESULT hr = S_OK;
386     const char *ptr;
387     size_t name_len;
388     unsigned int i;
389
390     ptr = data + t->start;
391
392     name_len = strlen(ptr) + 1;
393     t->name = HeapAlloc(GetProcessHeap(), 0, name_len);
394     if (!t->name)
395     {
396         ERR("Failed to allocate name memory\n");
397         return E_OUTOFMEMORY;
398     }
399
400     memcpy(t->name, ptr, name_len);
401     ptr += name_len;
402
403     TRACE("technique name: %s\n", t->name);
404
405     for (i = 0; i < t->pass_count; ++i)
406     {
407         hr = parse_fx10_pass(&t->passes[i], data);
408         if (FAILED(hr)) break;
409     }
410
411     return hr;
412 }
413
414 static HRESULT parse_fx10_body(struct d3d10_effect *e, const char *data, DWORD data_size)
415 {
416     const char *ptr = data + e->index_offset;
417     HRESULT hr = S_OK;
418     unsigned int i;
419
420     skip_dword_unknown(&ptr, 6);
421
422     e->techniques = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, e->technique_count * sizeof(*e->techniques));
423     if (!e->techniques)
424     {
425         ERR("Failed to allocate techniques memory\n");
426         return E_OUTOFMEMORY;
427     }
428
429     for (i = 0; i < e->technique_count; ++i)
430     {
431         struct d3d10_effect_technique *t = &e->techniques[i];
432
433         t->vtbl = &d3d10_effect_technique_vtbl;
434         t->effect = e;
435
436         hr = parse_fx10_technique_index(t, &ptr);
437         if (FAILED(hr)) break;
438
439         hr = parse_fx10_technique(t, data);
440         if (FAILED(hr)) break;
441     }
442
443     return hr;
444 }
445
446 static HRESULT parse_fx10(struct d3d10_effect *e, const char *data, DWORD data_size)
447 {
448     const char *ptr = data;
449     DWORD unknown;
450
451     /* version info? */
452     skip_dword_unknown(&ptr, 2);
453
454     read_dword(&ptr, &unknown);
455     FIXME("Unknown 0: %u\n", unknown);
456     read_dword(&ptr, &unknown);
457     FIXME("Unknown 1: %u\n", unknown);
458     read_dword(&ptr, &unknown);
459     FIXME("Unknown 2: %u\n", unknown);
460     read_dword(&ptr, &unknown);
461     FIXME("Unknown 3: %u\n", unknown);
462     read_dword(&ptr, &unknown);
463     FIXME("Unknown 4: %u\n", unknown);
464
465     read_dword(&ptr, &e->technique_count);
466     TRACE("Technique count: %u\n", e->technique_count);
467
468     read_dword(&ptr, &e->index_offset);
469     TRACE("Index offset: %#x\n", e->index_offset);
470
471     read_dword(&ptr, &unknown);
472     FIXME("Unknown 5: %u\n", unknown);
473     read_dword(&ptr, &unknown);
474     FIXME("Unknown 6: %u\n", unknown);
475     read_dword(&ptr, &unknown);
476     FIXME("Unknown 7: %u\n", unknown);
477
478     read_dword(&ptr, &e->blendstate_count);
479     TRACE("Blendstate count: %u\n", e->blendstate_count);
480
481     read_dword(&ptr, &unknown);
482     FIXME("Unknown 8: %u\n", unknown);
483     read_dword(&ptr, &unknown);
484     FIXME("Unknown 9: %u\n", unknown);
485     read_dword(&ptr, &unknown);
486     FIXME("Unknown 10: %u\n", unknown);
487     read_dword(&ptr, &unknown);
488     FIXME("Unknown 11: %u\n", unknown);
489     read_dword(&ptr, &unknown);
490     FIXME("Unknown 12: %u\n", unknown);
491     read_dword(&ptr, &unknown);
492     FIXME("Unknown 13: %u\n", unknown);
493
494     return parse_fx10_body(e, ptr, data_size - (ptr - data));
495 }
496
497 static HRESULT fx10_chunk_handler(const char *data, DWORD data_size, DWORD tag, void *ctx)
498 {
499     struct d3d10_effect *e = ctx;
500     char tag_str[5];
501
502     memcpy(tag_str, &tag, 4);
503     tag_str[4] = '\0';
504     TRACE("tag: %s\n", tag_str);
505
506     TRACE("chunk size: %#x\n", data_size);
507
508     switch(tag)
509     {
510         case TAG_FX10:
511             return parse_fx10(e, data, data_size);
512
513         default:
514             FIXME("Unhandled chunk %s\n", tag_str);
515             return S_OK;
516     }
517 }
518
519 HRESULT d3d10_effect_parse(struct d3d10_effect *This, const void *data, SIZE_T data_size)
520 {
521     return parse_dxbc(data, data_size, fx10_chunk_handler, This);
522 }
523
524 static void d3d10_effect_variable_destroy(struct d3d10_effect_variable *v)
525 {
526     TRACE("variable %p\n", v);
527
528     switch(v->type)
529     {
530         case D3D10_EVT_VERTEXSHADER:
531         case D3D10_EVT_PIXELSHADER:
532         case D3D10_EVT_GEOMETRYSHADER:
533             HeapFree(GetProcessHeap(), 0, ((struct d3d10_effect_shader_variable *)v->data)->input_signature);
534             break;
535
536         default:
537             break;
538     }
539     HeapFree(GetProcessHeap(), 0, v->data);
540 }
541
542 static HRESULT d3d10_effect_variable_apply(struct d3d10_effect_variable *v)
543 {
544     ID3D10Device *device = v->pass->technique->effect->device;
545
546     TRACE("variable %p, type %#x\n", v, v->type);
547
548     switch(v->type)
549     {
550         case D3D10_EVT_VERTEXSHADER:
551             ID3D10Device_VSSetShader(device, ((struct d3d10_effect_shader_variable *)v->data)->shader.vs);
552             return S_OK;
553
554         case D3D10_EVT_PIXELSHADER:
555             ID3D10Device_PSSetShader(device, ((struct d3d10_effect_shader_variable *)v->data)->shader.ps);
556             return S_OK;
557
558         case D3D10_EVT_GEOMETRYSHADER:
559             ID3D10Device_GSSetShader(device, ((struct d3d10_effect_shader_variable *)v->data)->shader.gs);
560             return S_OK;
561
562         default:
563             FIXME("Unhandled variable type %#x\n", v->type);
564             return E_FAIL;
565     }
566 }
567
568 static void d3d10_effect_pass_destroy(struct d3d10_effect_pass *p)
569 {
570     TRACE("pass %p\n", p);
571
572     HeapFree(GetProcessHeap(), 0, p->name);
573     if (p->variables)
574     {
575         unsigned int i;
576         for (i = 0; i < p->variable_count; ++i)
577         {
578             d3d10_effect_variable_destroy(&p->variables[i]);
579         }
580         HeapFree(GetProcessHeap(), 0, p->variables);
581     }
582 }
583
584 static void d3d10_effect_technique_destroy(struct d3d10_effect_technique *t)
585 {
586     TRACE("technique %p\n", t);
587
588     HeapFree(GetProcessHeap(), 0, t->name);
589     if (t->passes)
590     {
591         unsigned int i;
592         for (i = 0; i < t->pass_count; ++i)
593         {
594             d3d10_effect_pass_destroy(&t->passes[i]);
595         }
596         HeapFree(GetProcessHeap(), 0, t->passes);
597     }
598 }
599
600 /* IUnknown methods */
601
602 static HRESULT STDMETHODCALLTYPE d3d10_effect_QueryInterface(ID3D10Effect *iface, REFIID riid, void **object)
603 {
604     TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
605
606     if (IsEqualGUID(riid, &IID_ID3D10Effect)
607             || IsEqualGUID(riid, &IID_IUnknown))
608     {
609         IUnknown_AddRef(iface);
610         *object = iface;
611         return S_OK;
612     }
613
614     WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
615
616     *object = NULL;
617     return E_NOINTERFACE;
618 }
619
620 static ULONG STDMETHODCALLTYPE d3d10_effect_AddRef(ID3D10Effect *iface)
621 {
622     struct d3d10_effect *This = (struct d3d10_effect *)iface;
623     ULONG refcount = InterlockedIncrement(&This->refcount);
624
625     TRACE("%p increasing refcount to %u\n", This, refcount);
626
627     return refcount;
628 }
629
630 static ULONG STDMETHODCALLTYPE d3d10_effect_Release(ID3D10Effect *iface)
631 {
632     struct d3d10_effect *This = (struct d3d10_effect *)iface;
633     ULONG refcount = InterlockedDecrement(&This->refcount);
634
635     TRACE("%p decreasing refcount to %u\n", This, refcount);
636
637     if (!refcount)
638     {
639         if (This->techniques)
640         {
641             unsigned int i;
642             for (i = 0; i < This->technique_count; ++i)
643             {
644                 d3d10_effect_technique_destroy(&This->techniques[i]);
645             }
646             HeapFree(GetProcessHeap(), 0, This->techniques);
647         }
648         ID3D10Device_Release(This->device);
649         HeapFree(GetProcessHeap(), 0, This);
650     }
651
652     return refcount;
653 }
654
655 /* ID3D10Effect methods */
656
657 static BOOL STDMETHODCALLTYPE d3d10_effect_IsValid(ID3D10Effect *iface)
658 {
659     FIXME("iface %p stub!\n", iface);
660
661     return FALSE;
662 }
663
664 static BOOL STDMETHODCALLTYPE d3d10_effect_IsPool(ID3D10Effect *iface)
665 {
666     FIXME("iface %p stub!\n", iface);
667
668     return FALSE;
669 }
670
671 static HRESULT STDMETHODCALLTYPE d3d10_effect_GetDevice(ID3D10Effect *iface, ID3D10Device **device)
672 {
673     struct d3d10_effect *This = (struct d3d10_effect *)iface;
674
675     TRACE("iface %p, device %p\n", iface, device);
676
677     ID3D10Device_AddRef(This->device);
678     *device = This->device;
679
680     return S_OK;
681 }
682
683 static HRESULT STDMETHODCALLTYPE d3d10_effect_GetDesc(ID3D10Effect *iface, D3D10_EFFECT_DESC *desc)
684 {
685     FIXME("iface %p, desc %p stub!\n", iface, desc);
686
687     return E_NOTIMPL;
688 }
689
690 static struct ID3D10EffectConstantBuffer * STDMETHODCALLTYPE d3d10_effect_GetConstantBufferByIndex(ID3D10Effect *iface,
691         UINT index)
692 {
693     FIXME("iface %p, index %u stub!\n", iface, index);
694
695     return NULL;
696 }
697
698 static struct ID3D10EffectConstantBuffer * STDMETHODCALLTYPE d3d10_effect_GetConstantBufferByName(ID3D10Effect *iface,
699         LPCSTR name)
700 {
701     FIXME("iface %p, name \"%s\" stub!\n", iface, name);
702
703     return NULL;
704 }
705
706 static struct ID3D10EffectVariable * STDMETHODCALLTYPE d3d10_effect_GetVariableByIndex(ID3D10Effect *iface, UINT index)
707 {
708     FIXME("iface %p, index %u stub!\n", iface, index);
709
710     return NULL;
711 }
712
713 static struct ID3D10EffectVariable * STDMETHODCALLTYPE d3d10_effect_GetVariableByName(ID3D10Effect *iface, LPCSTR name)
714 {
715     FIXME("iface %p, name \"%s\" stub!\n", iface, name);
716
717     return NULL;
718 }
719
720 static struct ID3D10EffectVariable * STDMETHODCALLTYPE d3d10_effect_GetVariableBySemantic(ID3D10Effect *iface,
721         LPCSTR semantic)
722 {
723     FIXME("iface %p, semantic \"%s\" stub!\n", iface, semantic);
724
725     return NULL;
726 }
727
728 static struct ID3D10EffectTechnique * STDMETHODCALLTYPE d3d10_effect_GetTechniqueByIndex(ID3D10Effect *iface,
729         UINT index)
730 {
731     struct d3d10_effect *This = (struct d3d10_effect *)iface;
732     struct d3d10_effect_technique *t;
733
734     TRACE("iface %p, index %u\n", iface, index);
735
736     if (index >= This->technique_count)
737     {
738         WARN("Invalid index specified\n");
739         return NULL;
740     }
741
742     t = &This->techniques[index];
743
744     TRACE("Returning technique %p, \"%s\"\n", t, t->name);
745
746     return (ID3D10EffectTechnique *)t;
747 }
748
749 static struct ID3D10EffectTechnique * STDMETHODCALLTYPE d3d10_effect_GetTechniqueByName(ID3D10Effect *iface,
750         LPCSTR name)
751 {
752     struct d3d10_effect *This = (struct d3d10_effect *)iface;
753     unsigned int i;
754
755     TRACE("iface %p, name \"%s\"\n", iface, name);
756
757     for (i = 0; i < This->technique_count; ++i)
758     {
759         struct d3d10_effect_technique *t = &This->techniques[i];
760         if (!strcmp(t->name, name))
761         {
762             TRACE("Returning technique %p\n", t);
763             return (ID3D10EffectTechnique *)t;
764         }
765     }
766
767     return NULL;
768 }
769
770 static HRESULT STDMETHODCALLTYPE d3d10_effect_Optimize(ID3D10Effect *iface)
771 {
772     FIXME("iface %p stub!\n", iface);
773
774     return E_NOTIMPL;
775 }
776
777 static BOOL STDMETHODCALLTYPE d3d10_effect_IsOptimized(ID3D10Effect *iface)
778 {
779     FIXME("iface %p stub!\n", iface);
780
781     return FALSE;
782 }
783
784 const struct ID3D10EffectVtbl d3d10_effect_vtbl =
785 {
786     /* IUnknown methods */
787     d3d10_effect_QueryInterface,
788     d3d10_effect_AddRef,
789     d3d10_effect_Release,
790     /* ID3D10Effect methods */
791     d3d10_effect_IsValid,
792     d3d10_effect_IsPool,
793     d3d10_effect_GetDevice,
794     d3d10_effect_GetDesc,
795     d3d10_effect_GetConstantBufferByIndex,
796     d3d10_effect_GetConstantBufferByName,
797     d3d10_effect_GetVariableByIndex,
798     d3d10_effect_GetVariableByName,
799     d3d10_effect_GetVariableBySemantic,
800     d3d10_effect_GetTechniqueByIndex,
801     d3d10_effect_GetTechniqueByName,
802     d3d10_effect_Optimize,
803     d3d10_effect_IsOptimized,
804 };
805
806 /* ID3D10EffectTechnique methods */
807
808 static BOOL STDMETHODCALLTYPE d3d10_effect_technique_IsValid(ID3D10EffectTechnique *iface)
809 {
810     FIXME("iface %p stub!\n", iface);
811
812     return FALSE;
813 }
814
815 static HRESULT STDMETHODCALLTYPE d3d10_effect_technique_GetDesc(ID3D10EffectTechnique *iface,
816         D3D10_TECHNIQUE_DESC *desc)
817 {
818     struct d3d10_effect_technique *This = (struct d3d10_effect_technique *)iface;
819
820     TRACE("iface %p, desc %p\n", iface, desc);
821
822     desc->Name = This->name;
823     desc->Passes = This->pass_count;
824     WARN("Annotations not implemented\n");
825     desc->Annotations = 0;
826
827     return S_OK;
828 }
829
830 static struct ID3D10EffectVariable * STDMETHODCALLTYPE d3d10_effect_technique_GetAnnotationByIndex(
831         ID3D10EffectTechnique *iface, UINT index)
832 {
833     FIXME("iface %p, index %u stub!\n", iface, index);
834
835     return NULL;
836 }
837
838 static struct ID3D10EffectVariable * STDMETHODCALLTYPE d3d10_effect_technique_GetAnnotationByName(
839         ID3D10EffectTechnique *iface, LPCSTR name)
840 {
841     FIXME("iface %p, name \"%s\" stub!\n", iface, name);
842
843     return NULL;
844 }
845
846 static struct ID3D10EffectPass * STDMETHODCALLTYPE d3d10_effect_technique_GetPassByIndex(ID3D10EffectTechnique *iface,
847         UINT index)
848 {
849     struct d3d10_effect_technique *This = (struct d3d10_effect_technique *)iface;
850     struct d3d10_effect_pass *p;
851
852     TRACE("iface %p, index %u\n", iface, index);
853
854     if (index >= This->pass_count)
855     {
856         WARN("Invalid index specified\n");
857         return NULL;
858     }
859
860     p = &This->passes[index];
861
862     TRACE("Returning pass %p, \"%s\"\n", p, p->name);
863
864     return (ID3D10EffectPass *)p;
865 }
866
867 static struct ID3D10EffectPass * STDMETHODCALLTYPE d3d10_effect_technique_GetPassByName(ID3D10EffectTechnique *iface,
868         LPCSTR name)
869 {
870     struct d3d10_effect_technique *This = (struct d3d10_effect_technique *)iface;
871     unsigned int i;
872
873     TRACE("iface %p, name \"%s\"\n", iface, name);
874
875     for (i = 0; i < This->pass_count; ++i)
876     {
877         struct d3d10_effect_pass *p = &This->passes[i];
878         if (!strcmp(p->name, name))
879         {
880             TRACE("Returning pass %p\n", p);
881             return (ID3D10EffectPass *)p;
882         }
883     }
884
885     return NULL;
886 }
887
888 static HRESULT STDMETHODCALLTYPE d3d10_effect_technique_ComputeStateBlockMask(ID3D10EffectTechnique *iface,
889         D3D10_STATE_BLOCK_MASK *mask)
890 {
891     FIXME("iface %p,mask %p stub!\n", iface, mask);
892
893     return E_NOTIMPL;
894 }
895
896 static const struct ID3D10EffectTechniqueVtbl d3d10_effect_technique_vtbl =
897 {
898     /* ID3D10EffectTechnique methods */
899     d3d10_effect_technique_IsValid,
900     d3d10_effect_technique_GetDesc,
901     d3d10_effect_technique_GetAnnotationByIndex,
902     d3d10_effect_technique_GetAnnotationByName,
903     d3d10_effect_technique_GetPassByIndex,
904     d3d10_effect_technique_GetPassByName,
905     d3d10_effect_technique_ComputeStateBlockMask,
906 };
907
908 /* ID3D10EffectPass methods */
909
910 static BOOL STDMETHODCALLTYPE d3d10_effect_pass_IsValid(ID3D10EffectPass *iface)
911 {
912     FIXME("iface %p stub!\n", iface);
913
914     return FALSE;
915 }
916
917 static HRESULT STDMETHODCALLTYPE d3d10_effect_pass_GetDesc(ID3D10EffectPass *iface, D3D10_PASS_DESC *desc)
918 {
919     struct d3d10_effect_pass *This = (struct d3d10_effect_pass *)iface;
920     unsigned int i;
921
922     FIXME("iface %p, desc %p partial stub!\n", iface, desc);
923
924     memset(desc, 0, sizeof(*desc));
925     desc->Name = This->name;
926     for (i = 0; i < This->variable_count; ++i)
927     {
928         struct d3d10_effect_variable *v = &This->variables[i];
929         if (v->type == D3D10_EVT_VERTEXSHADER)
930         {
931             struct d3d10_effect_shader_variable *s = v->data;
932             desc->pIAInputSignature = (BYTE *)s->input_signature;
933             desc->IAInputSignatureSize = s->input_signature_size;
934             break;
935         }
936     }
937
938     return S_OK;
939 }
940
941 static HRESULT STDMETHODCALLTYPE d3d10_effect_pass_GetVertexShaderDesc(ID3D10EffectPass *iface,
942         D3D10_PASS_SHADER_DESC *desc)
943 {
944     FIXME("iface %p, desc %p stub!\n", iface, desc);
945
946     return E_NOTIMPL;
947 }
948
949 static HRESULT STDMETHODCALLTYPE d3d10_effect_pass_GetGeometryShaderDesc(ID3D10EffectPass *iface,
950         D3D10_PASS_SHADER_DESC *desc)
951 {
952     FIXME("iface %p, desc %p stub!\n", iface, desc);
953
954     return E_NOTIMPL;
955 }
956
957 static HRESULT STDMETHODCALLTYPE d3d10_effect_pass_GetPixelShaderDesc(ID3D10EffectPass *iface,
958         D3D10_PASS_SHADER_DESC *desc)
959 {
960     FIXME("iface %p, desc %p stub!\n", iface, desc);
961
962     return E_NOTIMPL;
963 }
964
965 static struct ID3D10EffectVariable * STDMETHODCALLTYPE d3d10_effect_pass_GetAnnotationByIndex(ID3D10EffectPass *iface,
966         UINT index)
967 {
968     FIXME("iface %p, index %u stub!\n", iface, index);
969
970     return NULL;
971 }
972
973 static struct ID3D10EffectVariable * STDMETHODCALLTYPE d3d10_effect_pass_GetAnnotationByName(ID3D10EffectPass *iface,
974         LPCSTR name)
975 {
976     FIXME("iface %p, name \"%s\" stub!\n", iface, name);
977
978     return NULL;
979 }
980
981 static HRESULT STDMETHODCALLTYPE d3d10_effect_pass_Apply(ID3D10EffectPass *iface, UINT flags)
982 {
983     struct d3d10_effect_pass *This = (struct d3d10_effect_pass *)iface;
984     HRESULT hr = S_OK;
985     unsigned int i;
986
987     TRACE("iface %p, flags %#x\n", iface, flags);
988
989     if (flags) FIXME("Ignoring flags (%#x)\n", flags);
990
991     for (i = 0; i < This->variable_count; ++i)
992     {
993         hr = d3d10_effect_variable_apply(&This->variables[i]);
994         if (FAILED(hr)) break;
995     }
996
997     return hr;
998 }
999
1000 static HRESULT STDMETHODCALLTYPE d3d10_effect_pass_ComputeStateBlockMask(ID3D10EffectPass *iface,
1001         D3D10_STATE_BLOCK_MASK *mask)
1002 {
1003     FIXME("iface %p, mask %p stub!\n", iface, mask);
1004
1005     return E_NOTIMPL;
1006 }
1007
1008 static const struct ID3D10EffectPassVtbl d3d10_effect_pass_vtbl =
1009 {
1010     /* ID3D10EffectPass methods */
1011     d3d10_effect_pass_IsValid,
1012     d3d10_effect_pass_GetDesc,
1013     d3d10_effect_pass_GetVertexShaderDesc,
1014     d3d10_effect_pass_GetGeometryShaderDesc,
1015     d3d10_effect_pass_GetPixelShaderDesc,
1016     d3d10_effect_pass_GetAnnotationByIndex,
1017     d3d10_effect_pass_GetAnnotationByName,
1018     d3d10_effect_pass_Apply,
1019     d3d10_effect_pass_ComputeStateBlockMask,
1020 };