wined3d: Keep better track of where we're using wined3d contexts.
[wine] / dlls / wined3d / stateblock.c
1 /*
2  * state block implementation
3  *
4  * Copyright 2002 Raphael Junqueira
5  * Copyright 2004 Jason Edmeades
6  * Copyright 2005 Oliver Stieber
7  * Copyright 2007 Stefan Dösinger for CodeWeavers
8  * Copyright 2009 Henri Verbeet for CodeWeavers
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24
25 #include "config.h"
26 #include "wined3d_private.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
29 #define GLINFO_LOCATION This->wineD3DDevice->adapter->gl_info
30
31 static const DWORD pixel_states_render[] =
32 {
33     WINED3DRS_ALPHABLENDENABLE,
34     WINED3DRS_ALPHAFUNC,
35     WINED3DRS_ALPHAREF,
36     WINED3DRS_ALPHATESTENABLE,
37     WINED3DRS_ANTIALIASEDLINEENABLE,
38     WINED3DRS_BLENDFACTOR,
39     WINED3DRS_BLENDOP,
40     WINED3DRS_BLENDOPALPHA,
41     WINED3DRS_CCW_STENCILFAIL,
42     WINED3DRS_CCW_STENCILPASS,
43     WINED3DRS_CCW_STENCILZFAIL,
44     WINED3DRS_COLORWRITEENABLE,
45     WINED3DRS_COLORWRITEENABLE1,
46     WINED3DRS_COLORWRITEENABLE2,
47     WINED3DRS_COLORWRITEENABLE3,
48     WINED3DRS_DEPTHBIAS,
49     WINED3DRS_DESTBLEND,
50     WINED3DRS_DESTBLENDALPHA,
51     WINED3DRS_DITHERENABLE,
52     WINED3DRS_FILLMODE,
53     WINED3DRS_FOGDENSITY,
54     WINED3DRS_FOGEND,
55     WINED3DRS_FOGSTART,
56     WINED3DRS_LASTPIXEL,
57     WINED3DRS_SCISSORTESTENABLE,
58     WINED3DRS_SEPARATEALPHABLENDENABLE,
59     WINED3DRS_SHADEMODE,
60     WINED3DRS_SLOPESCALEDEPTHBIAS,
61     WINED3DRS_SRCBLEND,
62     WINED3DRS_SRCBLENDALPHA,
63     WINED3DRS_SRGBWRITEENABLE,
64     WINED3DRS_STENCILENABLE,
65     WINED3DRS_STENCILFAIL,
66     WINED3DRS_STENCILFUNC,
67     WINED3DRS_STENCILMASK,
68     WINED3DRS_STENCILPASS,
69     WINED3DRS_STENCILREF,
70     WINED3DRS_STENCILWRITEMASK,
71     WINED3DRS_STENCILZFAIL,
72     WINED3DRS_TEXTUREFACTOR,
73     WINED3DRS_TWOSIDEDSTENCILMODE,
74     WINED3DRS_WRAP0,
75     WINED3DRS_WRAP1,
76     WINED3DRS_WRAP10,
77     WINED3DRS_WRAP11,
78     WINED3DRS_WRAP12,
79     WINED3DRS_WRAP13,
80     WINED3DRS_WRAP14,
81     WINED3DRS_WRAP15,
82     WINED3DRS_WRAP2,
83     WINED3DRS_WRAP3,
84     WINED3DRS_WRAP4,
85     WINED3DRS_WRAP5,
86     WINED3DRS_WRAP6,
87     WINED3DRS_WRAP7,
88     WINED3DRS_WRAP8,
89     WINED3DRS_WRAP9,
90     WINED3DRS_ZENABLE,
91     WINED3DRS_ZFUNC,
92     WINED3DRS_ZWRITEENABLE,
93 };
94
95 static const DWORD pixel_states_texture[] =
96 {
97     WINED3DTSS_ALPHAARG0,
98     WINED3DTSS_ALPHAARG1,
99     WINED3DTSS_ALPHAARG2,
100     WINED3DTSS_ALPHAOP,
101     WINED3DTSS_BUMPENVLOFFSET,
102     WINED3DTSS_BUMPENVLSCALE,
103     WINED3DTSS_BUMPENVMAT00,
104     WINED3DTSS_BUMPENVMAT01,
105     WINED3DTSS_BUMPENVMAT10,
106     WINED3DTSS_BUMPENVMAT11,
107     WINED3DTSS_COLORARG0,
108     WINED3DTSS_COLORARG1,
109     WINED3DTSS_COLORARG2,
110     WINED3DTSS_COLOROP,
111     WINED3DTSS_RESULTARG,
112     WINED3DTSS_TEXCOORDINDEX,
113     WINED3DTSS_TEXTURETRANSFORMFLAGS,
114 };
115
116 static const DWORD pixel_states_sampler[] =
117 {
118     WINED3DSAMP_ADDRESSU,
119     WINED3DSAMP_ADDRESSV,
120     WINED3DSAMP_ADDRESSW,
121     WINED3DSAMP_BORDERCOLOR,
122     WINED3DSAMP_MAGFILTER,
123     WINED3DSAMP_MINFILTER,
124     WINED3DSAMP_MIPFILTER,
125     WINED3DSAMP_MIPMAPLODBIAS,
126     WINED3DSAMP_MAXMIPLEVEL,
127     WINED3DSAMP_MAXANISOTROPY,
128     WINED3DSAMP_SRGBTEXTURE,
129     WINED3DSAMP_ELEMENTINDEX,
130 };
131
132 static const DWORD vertex_states_render[] =
133 {
134     WINED3DRS_ADAPTIVETESS_W,
135     WINED3DRS_ADAPTIVETESS_X,
136     WINED3DRS_ADAPTIVETESS_Y,
137     WINED3DRS_ADAPTIVETESS_Z,
138     WINED3DRS_AMBIENT,
139     WINED3DRS_AMBIENTMATERIALSOURCE,
140     WINED3DRS_CLIPPING,
141     WINED3DRS_CLIPPLANEENABLE,
142     WINED3DRS_COLORVERTEX,
143     WINED3DRS_CULLMODE,
144     WINED3DRS_DIFFUSEMATERIALSOURCE,
145     WINED3DRS_EMISSIVEMATERIALSOURCE,
146     WINED3DRS_ENABLEADAPTIVETESSELLATION,
147     WINED3DRS_FOGCOLOR,
148     WINED3DRS_FOGDENSITY,
149     WINED3DRS_FOGENABLE,
150     WINED3DRS_FOGEND,
151     WINED3DRS_FOGSTART,
152     WINED3DRS_FOGTABLEMODE,
153     WINED3DRS_FOGVERTEXMODE,
154     WINED3DRS_INDEXEDVERTEXBLENDENABLE,
155     WINED3DRS_LIGHTING,
156     WINED3DRS_LOCALVIEWER,
157     WINED3DRS_MAXTESSELLATIONLEVEL,
158     WINED3DRS_MINTESSELLATIONLEVEL,
159     WINED3DRS_MULTISAMPLEANTIALIAS,
160     WINED3DRS_MULTISAMPLEMASK,
161     WINED3DRS_NORMALDEGREE,
162     WINED3DRS_NORMALIZENORMALS,
163     WINED3DRS_PATCHEDGESTYLE,
164     WINED3DRS_POINTSCALE_A,
165     WINED3DRS_POINTSCALE_B,
166     WINED3DRS_POINTSCALE_C,
167     WINED3DRS_POINTSCALEENABLE,
168     WINED3DRS_POINTSIZE,
169     WINED3DRS_POINTSIZE_MAX,
170     WINED3DRS_POINTSIZE_MIN,
171     WINED3DRS_POINTSPRITEENABLE,
172     WINED3DRS_POSITIONDEGREE,
173     WINED3DRS_RANGEFOGENABLE,
174     WINED3DRS_SHADEMODE,
175     WINED3DRS_SPECULARENABLE,
176     WINED3DRS_SPECULARMATERIALSOURCE,
177     WINED3DRS_TWEENFACTOR,
178     WINED3DRS_VERTEXBLEND,
179 };
180
181 static const DWORD vertex_states_texture[] =
182 {
183     WINED3DTSS_TEXCOORDINDEX,
184     WINED3DTSS_TEXTURETRANSFORMFLAGS,
185 };
186
187 static const DWORD vertex_states_sampler[] =
188 {
189     WINED3DSAMP_DMAPOFFSET,
190 };
191
192 /* Allocates the correct amount of space for pixel and vertex shader constants,
193  * along with their set/changed flags on the given stateblock object
194  */
195 static HRESULT stateblock_allocate_shader_constants(IWineD3DStateBlockImpl *object)
196 {
197     IWineD3DDeviceImpl *device = object->wineD3DDevice;
198
199     /* Allocate space for floating point constants */
200     object->pixelShaderConstantF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
201             sizeof(float) * device->d3d_pshader_constantF * 4);
202     if (!object->pixelShaderConstantF) goto fail;
203
204     object->changed.pixelShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
205             sizeof(BOOL) * device->d3d_pshader_constantF);
206     if (!object->changed.pixelShaderConstantsF) goto fail;
207
208     object->vertexShaderConstantF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
209             sizeof(float) * device->d3d_vshader_constantF * 4);
210     if (!object->vertexShaderConstantF) goto fail;
211
212     object->changed.vertexShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
213             sizeof(BOOL) * device->d3d_vshader_constantF);
214     if (!object->changed.vertexShaderConstantsF) goto fail;
215
216     object->contained_vs_consts_f = HeapAlloc(GetProcessHeap(), 0,
217             sizeof(DWORD) * device->d3d_vshader_constantF);
218     if (!object->contained_vs_consts_f) goto fail;
219
220     object->contained_ps_consts_f = HeapAlloc(GetProcessHeap(), 0,
221             sizeof(DWORD) * device->d3d_pshader_constantF);
222     if (!object->contained_ps_consts_f) goto fail;
223
224     return WINED3D_OK;
225
226 fail:
227     ERR("Failed to allocate memory\n");
228     HeapFree(GetProcessHeap(), 0, object->pixelShaderConstantF);
229     HeapFree(GetProcessHeap(), 0, object->changed.pixelShaderConstantsF);
230     HeapFree(GetProcessHeap(), 0, object->vertexShaderConstantF);
231     HeapFree(GetProcessHeap(), 0, object->changed.vertexShaderConstantsF);
232     HeapFree(GetProcessHeap(), 0, object->contained_vs_consts_f);
233     HeapFree(GetProcessHeap(), 0, object->contained_ps_consts_f);
234     return E_OUTOFMEMORY;
235 }
236
237 static inline void stateblock_set_bits(DWORD *map, UINT map_size)
238 {
239     DWORD mask = (1 << (map_size & 0x1f)) - 1;
240     memset(map, 0xff, (map_size >> 5) * sizeof(*map));
241     if (mask) map[map_size >> 5] = mask;
242 }
243
244 /* Set all members of a stateblock savedstate to the given value */
245 static void stateblock_savedstates_set_all(SAVEDSTATES *states, DWORD vs_consts, DWORD ps_consts)
246 {
247     unsigned int i;
248
249     /* Single values */
250     states->primitive_type = 1;
251     states->indices = 1;
252     states->material = 1;
253     states->viewport = 1;
254     states->vertexDecl = 1;
255     states->pixelShader = 1;
256     states->vertexShader = 1;
257     states->scissorRect = 1;
258
259     /* Fixed size arrays */
260     states->streamSource = 0xffff;
261     states->streamFreq = 0xffff;
262     states->textures = 0xfffff;
263     stateblock_set_bits(states->transform, HIGHEST_TRANSFORMSTATE + 1);
264     stateblock_set_bits(states->renderState, WINEHIGHEST_RENDER_STATE + 1);
265     for (i = 0; i < MAX_TEXTURES; ++i) states->textureState[i] = 0x3ffff;
266     for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = 0x3fff;
267     states->clipplane = 0xffffffff;
268     states->pixelShaderConstantsB = 0xffff;
269     states->pixelShaderConstantsI = 0xffff;
270     states->vertexShaderConstantsB = 0xffff;
271     states->vertexShaderConstantsI = 0xffff;
272
273     /* Dynamically sized arrays */
274     memset(states->pixelShaderConstantsF, TRUE, sizeof(BOOL) * ps_consts);
275     memset(states->vertexShaderConstantsF, TRUE, sizeof(BOOL) * vs_consts);
276 }
277
278 static void stateblock_savedstates_set_pixel(SAVEDSTATES *states, const DWORD num_constants)
279 {
280     DWORD texture_mask = 0;
281     WORD sampler_mask = 0;
282     unsigned int i;
283
284     states->pixelShader = 1;
285
286     for (i = 0; i < sizeof(pixel_states_render) / sizeof(*pixel_states_render); ++i)
287     {
288         DWORD rs = pixel_states_render[i];
289         states->renderState[rs >> 5] |= 1 << (rs & 0x1f);
290     }
291
292     for (i = 0; i < sizeof(pixel_states_texture) / sizeof(*pixel_states_texture); ++i)
293         texture_mask |= 1 << pixel_states_texture[i];
294     for (i = 0; i < MAX_TEXTURES; ++i) states->textureState[i] = texture_mask;
295     for (i = 0; i < sizeof(pixel_states_sampler) / sizeof(*pixel_states_sampler); ++i)
296         sampler_mask |= 1 << pixel_states_sampler[i];
297     for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = sampler_mask;
298     states->pixelShaderConstantsB = 0xffff;
299     states->pixelShaderConstantsI = 0xffff;
300
301     memset(states->pixelShaderConstantsF, TRUE, sizeof(BOOL) * num_constants);
302 }
303
304 static void stateblock_savedstates_set_vertex(SAVEDSTATES *states, const DWORD num_constants)
305 {
306     DWORD texture_mask = 0;
307     WORD sampler_mask = 0;
308     unsigned int i;
309
310     states->vertexDecl = 1;
311     states->vertexShader = 1;
312
313     for (i = 0; i < sizeof(vertex_states_render) / sizeof(*vertex_states_render); ++i)
314     {
315         DWORD rs = vertex_states_render[i];
316         states->renderState[rs >> 5] |= 1 << (rs & 0x1f);
317     }
318
319     for (i = 0; i < sizeof(vertex_states_texture) / sizeof(*vertex_states_texture); ++i)
320         texture_mask |= 1 << vertex_states_texture[i];
321     for (i = 0; i < MAX_TEXTURES; ++i) states->textureState[i] = texture_mask;
322     for (i = 0; i < sizeof(vertex_states_sampler) / sizeof(*vertex_states_sampler); ++i)
323         sampler_mask |= 1 << vertex_states_sampler[i];
324     for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = sampler_mask;
325     states->vertexShaderConstantsB = 0xffff;
326     states->vertexShaderConstantsI = 0xffff;
327
328     memset(states->vertexShaderConstantsF, TRUE, sizeof(BOOL) * num_constants);
329 }
330
331 void stateblock_init_contained_states(IWineD3DStateBlockImpl *stateblock)
332 {
333     IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
334     unsigned int i, j;
335
336     for (i = 0; i <= WINEHIGHEST_RENDER_STATE >> 5; ++i)
337     {
338         DWORD map = stateblock->changed.renderState[i];
339         for (j = 0; map; map >>= 1, ++j)
340         {
341             if (!(map & 1)) continue;
342
343             stateblock->contained_render_states[stateblock->num_contained_render_states] = (i << 5) | j;
344             ++stateblock->num_contained_render_states;
345         }
346     }
347
348     for (i = 0; i <= HIGHEST_TRANSFORMSTATE >> 5; ++i)
349     {
350         DWORD map = stateblock->changed.transform[i];
351         for (j = 0; map; map >>= 1, ++j)
352         {
353             if (!(map & 1)) continue;
354
355             stateblock->contained_transform_states[stateblock->num_contained_transform_states] = (i << 5) | j;
356             ++stateblock->num_contained_transform_states;
357         }
358     }
359
360     for (i = 0; i < device->d3d_vshader_constantF; ++i)
361     {
362         if (stateblock->changed.vertexShaderConstantsF[i])
363         {
364             stateblock->contained_vs_consts_f[stateblock->num_contained_vs_consts_f] = i;
365             ++stateblock->num_contained_vs_consts_f;
366         }
367     }
368
369     for (i = 0; i < MAX_CONST_I; ++i)
370     {
371         if (stateblock->changed.vertexShaderConstantsI & (1 << i))
372         {
373             stateblock->contained_vs_consts_i[stateblock->num_contained_vs_consts_i] = i;
374             ++stateblock->num_contained_vs_consts_i;
375         }
376     }
377
378     for (i = 0; i < MAX_CONST_B; ++i)
379     {
380         if (stateblock->changed.vertexShaderConstantsB & (1 << i))
381         {
382             stateblock->contained_vs_consts_b[stateblock->num_contained_vs_consts_b] = i;
383             ++stateblock->num_contained_vs_consts_b;
384         }
385     }
386
387     for (i = 0; i < device->d3d_pshader_constantF; ++i)
388     {
389         if (stateblock->changed.pixelShaderConstantsF[i])
390         {
391             stateblock->contained_ps_consts_f[stateblock->num_contained_ps_consts_f] = i;
392             ++stateblock->num_contained_ps_consts_f;
393         }
394     }
395
396     for (i = 0; i < MAX_CONST_I; ++i)
397     {
398         if (stateblock->changed.pixelShaderConstantsI & (1 << i))
399         {
400             stateblock->contained_ps_consts_i[stateblock->num_contained_ps_consts_i] = i;
401             ++stateblock->num_contained_ps_consts_i;
402         }
403     }
404
405     for (i = 0; i < MAX_CONST_B; ++i)
406     {
407         if (stateblock->changed.pixelShaderConstantsB & (1 << i))
408         {
409             stateblock->contained_ps_consts_b[stateblock->num_contained_ps_consts_b] = i;
410             ++stateblock->num_contained_ps_consts_b;
411         }
412     }
413
414     for (i = 0; i < MAX_TEXTURES; ++i)
415     {
416         DWORD map = stateblock->changed.textureState[i];
417
418         for(j = 0; map; map >>= 1, ++j)
419         {
420             if (!(map & 1)) continue;
421
422             stateblock->contained_tss_states[stateblock->num_contained_tss_states].stage = i;
423             stateblock->contained_tss_states[stateblock->num_contained_tss_states].state = j;
424             ++stateblock->num_contained_tss_states;
425         }
426     }
427
428     for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
429     {
430         DWORD map = stateblock->changed.samplerState[i];
431
432         for (j = 0; map; map >>= 1, ++j)
433         {
434             if (!(map & 1)) continue;
435
436             stateblock->contained_sampler_states[stateblock->num_contained_sampler_states].stage = i;
437             stateblock->contained_sampler_states[stateblock->num_contained_sampler_states].state = j;
438             ++stateblock->num_contained_sampler_states;
439         }
440     }
441 }
442
443 static void stateblock_init_lights(IWineD3DStateBlockImpl *stateblock, struct list *light_map)
444 {
445     unsigned int i;
446
447     for (i = 0; i < LIGHTMAP_SIZE; ++i)
448     {
449         const struct wined3d_light_info *src_light;
450
451         LIST_FOR_EACH_ENTRY(src_light, &light_map[i], struct wined3d_light_info, entry)
452         {
453             struct wined3d_light_info *dst_light = HeapAlloc(GetProcessHeap(), 0, sizeof(*dst_light));
454
455             *dst_light = *src_light;
456             list_add_tail(&stateblock->lightMap[i], &dst_light->entry);
457         }
458     }
459 }
460
461 /**********************************************************
462  * IWineD3DStateBlockImpl IUnknown parts follows
463  **********************************************************/
464 static HRESULT  WINAPI IWineD3DStateBlockImpl_QueryInterface(IWineD3DStateBlock *iface,REFIID riid,LPVOID *ppobj)
465 {
466     IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
467     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
468     if (IsEqualGUID(riid, &IID_IUnknown)
469         || IsEqualGUID(riid, &IID_IWineD3DBase)
470         || IsEqualGUID(riid, &IID_IWineD3DStateBlock)){
471         IUnknown_AddRef(iface);
472         *ppobj = This;
473         return S_OK;
474     }
475     *ppobj = NULL;
476     return E_NOINTERFACE;
477 }
478
479 static ULONG  WINAPI IWineD3DStateBlockImpl_AddRef(IWineD3DStateBlock *iface) {
480     IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
481     ULONG refCount = InterlockedIncrement(&This->ref);
482
483     TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
484     return refCount;
485 }
486
487 static ULONG  WINAPI IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) {
488     IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
489     ULONG refCount = InterlockedDecrement(&This->ref);
490
491     TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
492
493     if (!refCount) {
494         int counter;
495
496         if (This->vertexDecl) IWineD3DVertexDeclaration_Release(This->vertexDecl);
497
498         for (counter = 0; counter < MAX_COMBINED_SAMPLERS; counter++)
499         {
500             if (This->textures[counter]) IWineD3DBaseTexture_Release(This->textures[counter]);
501         }
502
503         for (counter = 0; counter < MAX_STREAMS; counter++) {
504             if(This->streamSource[counter]) {
505                 if (IWineD3DBuffer_Release(This->streamSource[counter]))
506                 {
507                     TRACE("Vertex buffer still referenced by stateblock, applications has leaked Stream %u, buffer %p\n", counter, This->streamSource[counter]);
508                 }
509             }
510         }
511         if(This->pIndexData) IWineD3DBuffer_Release(This->pIndexData);
512         if(This->vertexShader) IWineD3DVertexShader_Release(This->vertexShader);
513         if(This->pixelShader) IWineD3DPixelShader_Release(This->pixelShader);
514
515         for(counter = 0; counter < LIGHTMAP_SIZE; counter++) {
516             struct list *e1, *e2;
517             LIST_FOR_EACH_SAFE(e1, e2, &This->lightMap[counter])
518             {
519                 struct wined3d_light_info *light = LIST_ENTRY(e1, struct wined3d_light_info, entry);
520                 list_remove(&light->entry);
521                 HeapFree(GetProcessHeap(), 0, light);
522             }
523         }
524
525         HeapFree(GetProcessHeap(), 0, This->vertexShaderConstantF);
526         HeapFree(GetProcessHeap(), 0, This->changed.vertexShaderConstantsF);
527         HeapFree(GetProcessHeap(), 0, This->pixelShaderConstantF);
528         HeapFree(GetProcessHeap(), 0, This->changed.pixelShaderConstantsF);
529         HeapFree(GetProcessHeap(), 0, This->contained_vs_consts_f);
530         HeapFree(GetProcessHeap(), 0, This->contained_ps_consts_f);
531         HeapFree(GetProcessHeap(), 0, This);
532     }
533     return refCount;
534 }
535
536 /**********************************************************
537  * IWineD3DStateBlockImpl parts follows
538  **********************************************************/
539 static HRESULT  WINAPI IWineD3DStateBlockImpl_GetParent(IWineD3DStateBlock *iface, IUnknown **pParent) {
540     IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
541     IUnknown_AddRef(This->parent);
542     *pParent = This->parent;
543     return WINED3D_OK;
544 }
545
546 static HRESULT  WINAPI IWineD3DStateBlockImpl_GetDevice(IWineD3DStateBlock *iface, IWineD3DDevice** ppDevice){
547
548     IWineD3DStateBlockImpl *This   = (IWineD3DStateBlockImpl *)iface;
549
550     *ppDevice = (IWineD3DDevice*)This->wineD3DDevice;
551     IWineD3DDevice_AddRef(*ppDevice);
552     return WINED3D_OK;
553
554 }
555
556 static void record_lights(IWineD3DStateBlockImpl *This, const IWineD3DStateBlockImpl *targetStateBlock)
557 {
558     UINT i;
559
560     /* Lights... For a recorded state block, we just had a chain of actions to perform,
561      * so we need to walk that chain and update any actions which differ
562      */
563     for(i = 0; i < LIGHTMAP_SIZE; i++) {
564         struct list *e, *f;
565         LIST_FOR_EACH(e, &This->lightMap[i]) {
566             BOOL updated = FALSE;
567             struct wined3d_light_info *src = LIST_ENTRY(e, struct wined3d_light_info, entry), *realLight;
568
569             /* Look up the light in the destination */
570             LIST_FOR_EACH(f, &targetStateBlock->lightMap[i]) {
571                 realLight = LIST_ENTRY(f, struct wined3d_light_info, entry);
572                 if (realLight->OriginalIndex == src->OriginalIndex)
573                 {
574                     src->OriginalParms = realLight->OriginalParms;
575
576                     if (realLight->glIndex == -1 && src->glIndex != -1)
577                     {
578                         /* Light disabled */
579                         This->activeLights[src->glIndex] = NULL;
580                     }
581                     else if (realLight->glIndex != -1 && src->glIndex == -1)
582                     {
583                         /* Light enabled */
584                         This->activeLights[realLight->glIndex] = src;
585                     }
586                     src->glIndex = realLight->glIndex;
587                     updated = TRUE;
588                     break;
589                 }
590             }
591
592             if (!updated)
593             {
594                 ERR("Light %u in stateblock %p does not exist in device stateblock %p.\n",
595                         src->OriginalIndex, This, targetStateBlock);
596             }
597         }
598     }
599 }
600
601 static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
602 {
603     IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
604     IWineD3DStateBlockImpl *targetStateBlock = This->wineD3DDevice->stateBlock;
605     unsigned int i;
606     DWORD map;
607
608     TRACE("(%p) : Updating state block %p ------------------v\n", targetStateBlock, This);
609
610     if (This->changed.vertexShader && This->vertexShader != targetStateBlock->vertexShader)
611     {
612         TRACE("Updating vertex shader from %p to %p\n", This->vertexShader, targetStateBlock->vertexShader);
613
614         if (targetStateBlock->vertexShader) IWineD3DVertexShader_AddRef(targetStateBlock->vertexShader);
615         if (This->vertexShader) IWineD3DVertexShader_Release(This->vertexShader);
616         This->vertexShader = targetStateBlock->vertexShader;
617     }
618
619     /* Vertex Shader Float Constants */
620     for (i = 0; i < This->num_contained_vs_consts_f; ++i)
621     {
622         unsigned int idx = This->contained_vs_consts_f[i];
623
624         TRACE("Setting %p from %p %u to {%.8e, %.8e, %.8e, %.8e}.\n",
625                 This, targetStateBlock, idx,
626                 targetStateBlock->vertexShaderConstantF[idx * 4 + 0],
627                 targetStateBlock->vertexShaderConstantF[idx * 4 + 1],
628                 targetStateBlock->vertexShaderConstantF[idx * 4 + 2],
629                 targetStateBlock->vertexShaderConstantF[idx * 4 + 3]);
630
631         This->vertexShaderConstantF[idx * 4 + 0] = targetStateBlock->vertexShaderConstantF[idx * 4 + 0];
632         This->vertexShaderConstantF[idx * 4 + 1] = targetStateBlock->vertexShaderConstantF[idx * 4 + 1];
633         This->vertexShaderConstantF[idx * 4 + 2] = targetStateBlock->vertexShaderConstantF[idx * 4 + 2];
634         This->vertexShaderConstantF[idx * 4 + 3] = targetStateBlock->vertexShaderConstantF[idx * 4 + 3];
635     }
636
637     /* Vertex Shader Integer Constants */
638     for (i = 0; i < This->num_contained_vs_consts_i; ++i)
639     {
640         unsigned int idx = This->contained_vs_consts_i[i];
641
642         TRACE("Setting %p from %p %u to {%d, %d, %d, %d}.\n",
643                 This, targetStateBlock, idx,
644                 targetStateBlock->vertexShaderConstantI[idx * 4 + 0],
645                 targetStateBlock->vertexShaderConstantI[idx * 4 + 1],
646                 targetStateBlock->vertexShaderConstantI[idx * 4 + 2],
647                 targetStateBlock->vertexShaderConstantI[idx * 4 + 3]);
648
649         This->vertexShaderConstantI[idx * 4 + 0] = targetStateBlock->vertexShaderConstantI[idx * 4 + 0];
650         This->vertexShaderConstantI[idx * 4 + 1] = targetStateBlock->vertexShaderConstantI[idx * 4 + 1];
651         This->vertexShaderConstantI[idx * 4 + 2] = targetStateBlock->vertexShaderConstantI[idx * 4 + 2];
652         This->vertexShaderConstantI[idx * 4 + 3] = targetStateBlock->vertexShaderConstantI[idx * 4 + 3];
653     }
654
655     /* Vertex Shader Boolean Constants */
656     for (i = 0; i < This->num_contained_vs_consts_b; ++i)
657     {
658         unsigned int idx = This->contained_vs_consts_b[i];
659
660         TRACE("Setting %p from %p %u to %s.\n",
661                 This, targetStateBlock, idx,
662                 targetStateBlock->vertexShaderConstantB[idx] ? "TRUE" : "FALSE");
663
664         This->vertexShaderConstantB[idx] = targetStateBlock->vertexShaderConstantB[idx];
665     }
666
667     /* Pixel Shader Float Constants */
668     for (i = 0; i < This->num_contained_ps_consts_f; ++i)
669     {
670         unsigned int idx = This->contained_ps_consts_f[i];
671
672         TRACE("Setting %p from %p %u to {%.8e, %.8e, %.8e, %.8e}.\n",
673                 This, targetStateBlock, idx,
674                 targetStateBlock->pixelShaderConstantF[idx * 4 + 0],
675                 targetStateBlock->pixelShaderConstantF[idx * 4 + 1],
676                 targetStateBlock->pixelShaderConstantF[idx * 4 + 2],
677                 targetStateBlock->pixelShaderConstantF[idx * 4 + 3]);
678
679         This->pixelShaderConstantF[idx * 4 + 0] = targetStateBlock->pixelShaderConstantF[idx * 4 + 0];
680         This->pixelShaderConstantF[idx * 4 + 1] = targetStateBlock->pixelShaderConstantF[idx * 4 + 1];
681         This->pixelShaderConstantF[idx * 4 + 2] = targetStateBlock->pixelShaderConstantF[idx * 4 + 2];
682         This->pixelShaderConstantF[idx * 4 + 3] = targetStateBlock->pixelShaderConstantF[idx * 4 + 3];
683     }
684
685     /* Pixel Shader Integer Constants */
686     for (i = 0; i < This->num_contained_ps_consts_i; ++i)
687     {
688         unsigned int idx = This->contained_ps_consts_i[i];
689         TRACE("Setting %p from %p %u to {%d, %d, %d, %d}.\n",
690                 This, targetStateBlock, idx,
691                 targetStateBlock->pixelShaderConstantI[idx * 4 + 0],
692                 targetStateBlock->pixelShaderConstantI[idx * 4 + 1],
693                 targetStateBlock->pixelShaderConstantI[idx * 4 + 2],
694                 targetStateBlock->pixelShaderConstantI[idx * 4 + 3]);
695
696         This->pixelShaderConstantI[idx * 4 + 0] = targetStateBlock->pixelShaderConstantI[idx * 4 + 0];
697         This->pixelShaderConstantI[idx * 4 + 1] = targetStateBlock->pixelShaderConstantI[idx * 4 + 1];
698         This->pixelShaderConstantI[idx * 4 + 2] = targetStateBlock->pixelShaderConstantI[idx * 4 + 2];
699         This->pixelShaderConstantI[idx * 4 + 3] = targetStateBlock->pixelShaderConstantI[idx * 4 + 3];
700     }
701
702     /* Pixel Shader Boolean Constants */
703     for (i = 0; i < This->num_contained_ps_consts_b; ++i)
704     {
705         unsigned int idx = This->contained_ps_consts_b[i];
706         TRACE("Setting %p from %p %u to %s.\n", This, targetStateBlock, idx,
707                 targetStateBlock->pixelShaderConstantB[idx] ? "TRUE" : "FALSE");
708
709         This->pixelShaderConstantB[idx] = targetStateBlock->pixelShaderConstantB[idx];
710     }
711
712     /* Others + Render & Texture */
713     for (i = 0; i < This->num_contained_transform_states; ++i)
714     {
715         WINED3DTRANSFORMSTATETYPE transform = This->contained_transform_states[i];
716
717         TRACE("Updating transform %#x.\n", transform);
718
719         This->transforms[transform] = targetStateBlock->transforms[transform];
720     }
721
722     if (This->changed.primitive_type) This->gl_primitive_type = targetStateBlock->gl_primitive_type;
723
724     if (This->changed.indices
725             && ((This->pIndexData != targetStateBlock->pIndexData)
726                 || (This->baseVertexIndex != targetStateBlock->baseVertexIndex)
727                 || (This->IndexFmt != targetStateBlock->IndexFmt)))
728     {
729         TRACE("Updating pIndexData to %p, baseVertexIndex to %d.\n",
730                 targetStateBlock->pIndexData, targetStateBlock->baseVertexIndex);
731
732         if (targetStateBlock->pIndexData) IWineD3DBuffer_AddRef(targetStateBlock->pIndexData);
733         if (This->pIndexData) IWineD3DBuffer_Release(This->pIndexData);
734         This->pIndexData = targetStateBlock->pIndexData;
735         This->baseVertexIndex = targetStateBlock->baseVertexIndex;
736         This->IndexFmt = targetStateBlock->IndexFmt;
737     }
738
739     if (This->changed.vertexDecl && This->vertexDecl != targetStateBlock->vertexDecl
740             && (This->blockType != WINED3DSBT_RECORDED
741                     || ((IWineD3DImpl *)This->wineD3DDevice->wineD3D)->dxVersion != 9))
742     {
743         TRACE("Updating vertex declaration from %p to %p.\n", This->vertexDecl, targetStateBlock->vertexDecl);
744
745         if (targetStateBlock->vertexDecl) IWineD3DVertexDeclaration_AddRef(targetStateBlock->vertexDecl);
746         if (This->vertexDecl) IWineD3DVertexDeclaration_Release(This->vertexDecl);
747         This->vertexDecl = targetStateBlock->vertexDecl;
748     }
749
750     if (This->changed.material
751             && memcmp(&targetStateBlock->material, &This->material, sizeof(This->material)))
752     {
753         TRACE("Updating material.\n");
754
755         This->material = targetStateBlock->material;
756     }
757
758     if (This->changed.viewport
759             && memcmp(&targetStateBlock->viewport, &This->viewport, sizeof(This->viewport)))
760     {
761         TRACE("Updating viewport.\n");
762
763         This->viewport = targetStateBlock->viewport;
764     }
765
766     if(This->changed.scissorRect
767             && memcmp(&targetStateBlock->scissorRect, &This->scissorRect, sizeof(This->scissorRect)))
768     {
769         TRACE("Updating scissor rect.\n");
770
771         targetStateBlock->scissorRect = This->scissorRect;
772     }
773
774     map = This->changed.streamSource;
775     for (i = 0; map; map >>= 1, ++i)
776     {
777         if (!(map & 1)) continue;
778
779         if (This->streamStride[i] != targetStateBlock->streamStride[i]
780                 || This->streamSource[i] != targetStateBlock->streamSource[i])
781         {
782             TRACE("Updating stream source %u to %p, stride to %u.\n",
783                     i, targetStateBlock->streamSource[i], targetStateBlock->streamStride[i]);
784
785             This->streamStride[i] = targetStateBlock->streamStride[i];
786             if (targetStateBlock->streamSource[i]) IWineD3DBuffer_AddRef(targetStateBlock->streamSource[i]);
787             if (This->streamSource[i]) IWineD3DBuffer_Release(This->streamSource[i]);
788             This->streamSource[i] = targetStateBlock->streamSource[i];
789         }
790     }
791
792     map = This->changed.streamFreq;
793     for (i = 0; map; map >>= 1, ++i)
794     {
795         if (!(map & 1)) continue;
796
797         if (This->streamFreq[i] != targetStateBlock->streamFreq[i]
798                 || This->streamFlags[i] != targetStateBlock->streamFlags[i])
799         {
800             TRACE("Updating stream frequency %u to %u flags to %#x.\n",
801                     i, targetStateBlock->streamFreq[i], targetStateBlock->streamFlags[i]);
802
803             This->streamFreq[i] = targetStateBlock->streamFreq[i];
804             This->streamFlags[i] = targetStateBlock->streamFlags[i];
805         }
806     }
807
808     map = This->changed.clipplane;
809     for (i = 0; map; map >>= 1, ++i)
810     {
811         if (!(map & 1)) continue;
812
813         if (memcmp(targetStateBlock->clipplane[i], This->clipplane[i], sizeof(*This->clipplane)))
814         {
815             TRACE("Updating clipplane %u.\n", i);
816             memcpy(This->clipplane[i], targetStateBlock->clipplane[i], sizeof(*This->clipplane));
817         }
818     }
819
820     /* Render */
821     for (i = 0; i < This->num_contained_render_states; ++i)
822     {
823         WINED3DRENDERSTATETYPE rs = This->contained_render_states[i];
824
825         TRACE("Updating renderState %#x to %u.\n", rs, targetStateBlock->renderState[rs]);
826
827         This->renderState[rs] = targetStateBlock->renderState[rs];
828     }
829
830     /* Texture states */
831     for (i = 0; i < This->num_contained_tss_states; ++i)
832     {
833         DWORD stage = This->contained_tss_states[i].stage;
834         DWORD state = This->contained_tss_states[i].state;
835
836         TRACE("Updating texturestage state %u, %u to %u (was %u).\n", stage, state,
837                 targetStateBlock->textureState[stage][state], This->textureState[stage][state]);
838
839         This->textureState[stage][state] = targetStateBlock->textureState[stage][state];
840     }
841
842     /* Samplers */
843     map = This->changed.textures;
844     for (i = 0; map; map >>= 1, ++i)
845     {
846         if (!(map & 1)) continue;
847
848         TRACE("Updating texture %u to %p (was %p).\n", i, targetStateBlock->textures[i], This->textures[i]);
849
850         if (targetStateBlock->textures[i]) IWineD3DBaseTexture_AddRef(targetStateBlock->textures[i]);
851         if (This->textures[i]) IWineD3DBaseTexture_Release(This->textures[i]);
852         This->textures[i] = targetStateBlock->textures[i];
853     }
854
855     for (i = 0; i < This->num_contained_sampler_states; ++i)
856     {
857         DWORD stage = This->contained_sampler_states[i].stage;
858         DWORD state = This->contained_sampler_states[i].state;
859
860         TRACE("Updating sampler state %u, %u to %u (was %u).\n", stage, state,
861                 targetStateBlock->samplerState[stage][state], This->samplerState[stage][state]);
862
863         This->samplerState[stage][state] = targetStateBlock->samplerState[stage][state];
864     }
865
866     if (This->changed.pixelShader && This->pixelShader != targetStateBlock->pixelShader)
867     {
868         if (targetStateBlock->pixelShader) IWineD3DPixelShader_AddRef(targetStateBlock->pixelShader);
869         if (This->pixelShader) IWineD3DPixelShader_Release(This->pixelShader);
870         This->pixelShader = targetStateBlock->pixelShader;
871     }
872
873     record_lights(This, targetStateBlock);
874
875     TRACE("(%p) : Updated state block %p ------------------^\n", targetStateBlock, This);
876
877     return WINED3D_OK;
878 }
879
880 static void apply_lights(IWineD3DDevice *pDevice, const IWineD3DStateBlockImpl *This)
881 {
882     UINT i;
883     for(i = 0; i < LIGHTMAP_SIZE; i++) {
884         struct list *e;
885
886         LIST_FOR_EACH(e, &This->lightMap[i])
887         {
888             const struct wined3d_light_info *light = LIST_ENTRY(e, struct wined3d_light_info, entry);
889
890             IWineD3DDevice_SetLight(pDevice, light->OriginalIndex, &light->OriginalParms);
891             IWineD3DDevice_SetLightEnable(pDevice, light->OriginalIndex, light->glIndex != -1);
892         }
893     }
894 }
895
896 static HRESULT WINAPI IWineD3DStateBlockImpl_Apply(IWineD3DStateBlock *iface)
897 {
898     IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
899     IWineD3DDevice *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
900     unsigned int i;
901     DWORD map;
902
903     TRACE("(%p) : Applying state block %p ------------------v\n", This, pDevice);
904
905     TRACE("Blocktype: %d\n", This->blockType);
906
907     if (This->changed.vertexShader) IWineD3DDevice_SetVertexShader(pDevice, This->vertexShader);
908
909     /* Vertex Shader Constants */
910     for (i = 0; i < This->num_contained_vs_consts_f; ++i)
911     {
912         IWineD3DDevice_SetVertexShaderConstantF(pDevice, This->contained_vs_consts_f[i],
913                 This->vertexShaderConstantF + This->contained_vs_consts_f[i] * 4, 1);
914     }
915     for (i = 0; i < This->num_contained_vs_consts_i; ++i)
916     {
917         IWineD3DDevice_SetVertexShaderConstantI(pDevice, This->contained_vs_consts_i[i],
918                 This->vertexShaderConstantI + This->contained_vs_consts_i[i] * 4, 1);
919     }
920     for (i = 0; i < This->num_contained_vs_consts_b; ++i)
921     {
922         IWineD3DDevice_SetVertexShaderConstantB(pDevice, This->contained_vs_consts_b[i],
923                 This->vertexShaderConstantB + This->contained_vs_consts_b[i], 1);
924     }
925
926     apply_lights(pDevice, This);
927
928     if (This->changed.pixelShader) IWineD3DDevice_SetPixelShader(pDevice, This->pixelShader);
929
930     /* Pixel Shader Constants */
931     for (i = 0; i < This->num_contained_ps_consts_f; ++i)
932     {
933         IWineD3DDevice_SetPixelShaderConstantF(pDevice, This->contained_ps_consts_f[i],
934                 This->pixelShaderConstantF + This->contained_ps_consts_f[i] * 4, 1);
935     }
936     for (i = 0; i < This->num_contained_ps_consts_i; ++i)
937     {
938         IWineD3DDevice_SetPixelShaderConstantI(pDevice, This->contained_ps_consts_i[i],
939                 This->pixelShaderConstantI + This->contained_ps_consts_i[i] * 4, 1);
940     }
941     for (i = 0; i < This->num_contained_ps_consts_b; ++i)
942     {
943         IWineD3DDevice_SetPixelShaderConstantB(pDevice, This->contained_ps_consts_b[i],
944                 This->pixelShaderConstantB + This->contained_ps_consts_b[i], 1);
945     }
946
947     /* Render */
948     for (i = 0; i < This->num_contained_render_states; ++i)
949     {
950         IWineD3DDevice_SetRenderState(pDevice, This->contained_render_states[i],
951                 This->renderState[This->contained_render_states[i]]);
952     }
953
954     /* Texture states */
955     for (i = 0; i < This->num_contained_tss_states; ++i)
956     {
957         DWORD stage = This->contained_tss_states[i].stage;
958         DWORD state = This->contained_tss_states[i].state;
959
960         IWineD3DDevice_SetTextureStageState(pDevice, stage, state, This->textureState[stage][state]);
961     }
962
963     /* Sampler states */
964     for (i = 0; i < This->num_contained_sampler_states; ++i)
965     {
966         DWORD stage = This->contained_sampler_states[i].stage;
967         DWORD state = This->contained_sampler_states[i].state;
968         DWORD value = This->samplerState[stage][state];
969
970         if (stage >= MAX_FRAGMENT_SAMPLERS) stage += WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS;
971         IWineD3DDevice_SetSamplerState(pDevice, stage, state, value);
972     }
973
974     for (i = 0; i < This->num_contained_transform_states; ++i)
975     {
976         IWineD3DDevice_SetTransform(pDevice, This->contained_transform_states[i],
977                 &This->transforms[This->contained_transform_states[i]]);
978     }
979
980     if (This->changed.primitive_type)
981     {
982         This->wineD3DDevice->updateStateBlock->changed.primitive_type = TRUE;
983         This->wineD3DDevice->updateStateBlock->gl_primitive_type = This->gl_primitive_type;
984     }
985
986     if (This->changed.indices)
987     {
988         IWineD3DDevice_SetIndexBuffer(pDevice, This->pIndexData, This->IndexFmt);
989         IWineD3DDevice_SetBaseVertexIndex(pDevice, This->baseVertexIndex);
990     }
991
992     if (This->changed.vertexDecl)
993     {
994         IWineD3DDevice_SetVertexDeclaration(pDevice, This->vertexDecl);
995     }
996
997     if (This->changed.material)
998     {
999         IWineD3DDevice_SetMaterial(pDevice, &This->material);
1000     }
1001
1002     if (This->changed.viewport)
1003     {
1004         IWineD3DDevice_SetViewport(pDevice, &This->viewport);
1005     }
1006
1007     if (This->changed.scissorRect)
1008     {
1009         IWineD3DDevice_SetScissorRect(pDevice, &This->scissorRect);
1010     }
1011
1012     map = This->changed.streamSource;
1013     for (i = 0; map; map >>= 1, ++i)
1014     {
1015         if (map & 1) IWineD3DDevice_SetStreamSource(pDevice, i, This->streamSource[i], 0, This->streamStride[i]);
1016     }
1017
1018     map = This->changed.streamFreq;
1019     for (i = 0; map; map >>= 1, ++i)
1020     {
1021         if (map & 1) IWineD3DDevice_SetStreamSourceFreq(pDevice, i, This->streamFreq[i] | This->streamFlags[i]);
1022     }
1023
1024     map = This->changed.textures;
1025     for (i = 0; map; map >>= 1, ++i)
1026     {
1027         DWORD stage;
1028
1029         if (!(map & 1)) continue;
1030
1031         stage = i < MAX_FRAGMENT_SAMPLERS ? i : WINED3DVERTEXTEXTURESAMPLER0 + i - MAX_FRAGMENT_SAMPLERS;
1032         IWineD3DDevice_SetTexture(pDevice, stage, This->textures[i]);
1033     }
1034
1035     map = This->changed.clipplane;
1036     for (i = 0; map; map >>= 1, ++i)
1037     {
1038         float clip[4];
1039
1040         if (!(map & 1)) continue;
1041
1042         clip[0] = This->clipplane[i][0];
1043         clip[1] = This->clipplane[i][1];
1044         clip[2] = This->clipplane[i][2];
1045         clip[3] = This->clipplane[i][3];
1046         IWineD3DDevice_SetClipPlane(pDevice, i, clip);
1047     }
1048
1049     This->wineD3DDevice->stateBlock->lowest_disabled_stage = MAX_TEXTURES - 1;
1050     for (i = 0; i < MAX_TEXTURES - 1; ++i)
1051     {
1052         if (This->wineD3DDevice->stateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE)
1053         {
1054             This->wineD3DDevice->stateBlock->lowest_disabled_stage = i;
1055             break;
1056         }
1057     }
1058     TRACE("(%p) : Applied state block %p ------------------^\n", This, pDevice);
1059
1060     return WINED3D_OK;
1061 }
1062
1063 static HRESULT  WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStateBlock* iface) {
1064     IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
1065     IWineD3DDevice         *device = (IWineD3DDevice *)This->wineD3DDevice;
1066     IWineD3DDeviceImpl     *ThisDevice = (IWineD3DDeviceImpl *)device;
1067     const struct wined3d_gl_info *gl_info = &This->wineD3DDevice->adapter->gl_info;
1068     union {
1069         WINED3DLINEPATTERN lp;
1070         DWORD d;
1071     } lp;
1072     union {
1073         float f;
1074         DWORD d;
1075     } tmpfloat;
1076     unsigned int i;
1077     IWineD3DSwapChain *swapchain;
1078     IWineD3DSurface *backbuffer;
1079     HRESULT hr;
1080
1081     /* Note this may have a large overhead but it should only be executed
1082        once, in order to initialize the complete state of the device and
1083        all opengl equivalents                                            */
1084     TRACE("(%p) -----------------------> Setting up device defaults... %p\n", This, This->wineD3DDevice);
1085     /* TODO: make a special stateblock type for the primary stateblock (it never gets applied so it doesn't need a real type) */
1086     This->blockType = WINED3DSBT_INIT;
1087
1088     /* Set some of the defaults for lights, transforms etc */
1089     memcpy(&This->transforms[WINED3DTS_PROJECTION], identity, sizeof(identity));
1090     memcpy(&This->transforms[WINED3DTS_VIEW], identity, sizeof(identity));
1091     for (i = 0; i < 256; ++i) {
1092       memcpy(&This->transforms[WINED3DTS_WORLDMATRIX(i)], identity, sizeof(identity));
1093     }
1094
1095     TRACE("Render states\n");
1096     /* Render states: */
1097     if (ThisDevice->auto_depth_stencil_buffer != NULL) {
1098        IWineD3DDevice_SetRenderState(device, WINED3DRS_ZENABLE,       WINED3DZB_TRUE);
1099     } else {
1100        IWineD3DDevice_SetRenderState(device, WINED3DRS_ZENABLE,       WINED3DZB_FALSE);
1101     }
1102     IWineD3DDevice_SetRenderState(device, WINED3DRS_FILLMODE,         WINED3DFILL_SOLID);
1103     IWineD3DDevice_SetRenderState(device, WINED3DRS_SHADEMODE,        WINED3DSHADE_GOURAUD);
1104     lp.lp.wRepeatFactor = 0;
1105     lp.lp.wLinePattern  = 0;
1106     IWineD3DDevice_SetRenderState(device, WINED3DRS_LINEPATTERN,      lp.d);
1107     IWineD3DDevice_SetRenderState(device, WINED3DRS_ZWRITEENABLE,     TRUE);
1108     IWineD3DDevice_SetRenderState(device, WINED3DRS_ALPHATESTENABLE,  FALSE);
1109     IWineD3DDevice_SetRenderState(device, WINED3DRS_LASTPIXEL,        TRUE);
1110     IWineD3DDevice_SetRenderState(device, WINED3DRS_SRCBLEND,         WINED3DBLEND_ONE);
1111     IWineD3DDevice_SetRenderState(device, WINED3DRS_DESTBLEND,        WINED3DBLEND_ZERO);
1112     IWineD3DDevice_SetRenderState(device, WINED3DRS_CULLMODE,         WINED3DCULL_CCW);
1113     IWineD3DDevice_SetRenderState(device, WINED3DRS_ZFUNC,            WINED3DCMP_LESSEQUAL);
1114     IWineD3DDevice_SetRenderState(device, WINED3DRS_ALPHAFUNC,        WINED3DCMP_ALWAYS);
1115     IWineD3DDevice_SetRenderState(device, WINED3DRS_ALPHAREF,         0);
1116     IWineD3DDevice_SetRenderState(device, WINED3DRS_DITHERENABLE,     FALSE);
1117     IWineD3DDevice_SetRenderState(device, WINED3DRS_ALPHABLENDENABLE, FALSE);
1118     IWineD3DDevice_SetRenderState(device, WINED3DRS_FOGENABLE,        FALSE);
1119     IWineD3DDevice_SetRenderState(device, WINED3DRS_SPECULARENABLE,   FALSE);
1120     IWineD3DDevice_SetRenderState(device, WINED3DRS_ZVISIBLE,         0);
1121     IWineD3DDevice_SetRenderState(device, WINED3DRS_FOGCOLOR,         0);
1122     IWineD3DDevice_SetRenderState(device, WINED3DRS_FOGTABLEMODE,     WINED3DFOG_NONE);
1123     tmpfloat.f = 0.0f;
1124     IWineD3DDevice_SetRenderState(device, WINED3DRS_FOGSTART,         tmpfloat.d);
1125     tmpfloat.f = 1.0f;
1126     IWineD3DDevice_SetRenderState(device, WINED3DRS_FOGEND,           tmpfloat.d);
1127     tmpfloat.f = 1.0f;
1128     IWineD3DDevice_SetRenderState(device, WINED3DRS_FOGDENSITY,       tmpfloat.d);
1129     IWineD3DDevice_SetRenderState(device, WINED3DRS_EDGEANTIALIAS,    FALSE);
1130     IWineD3DDevice_SetRenderState(device, WINED3DRS_ZBIAS,            0);
1131     IWineD3DDevice_SetRenderState(device, WINED3DRS_RANGEFOGENABLE,   FALSE);
1132     IWineD3DDevice_SetRenderState(device, WINED3DRS_STENCILENABLE,    FALSE);
1133     IWineD3DDevice_SetRenderState(device, WINED3DRS_STENCILFAIL,      WINED3DSTENCILOP_KEEP);
1134     IWineD3DDevice_SetRenderState(device, WINED3DRS_STENCILZFAIL,     WINED3DSTENCILOP_KEEP);
1135     IWineD3DDevice_SetRenderState(device, WINED3DRS_STENCILPASS,      WINED3DSTENCILOP_KEEP);
1136     IWineD3DDevice_SetRenderState(device, WINED3DRS_STENCILREF,       0);
1137     IWineD3DDevice_SetRenderState(device, WINED3DRS_STENCILMASK,      0xFFFFFFFF);
1138     IWineD3DDevice_SetRenderState(device, WINED3DRS_STENCILFUNC,      WINED3DCMP_ALWAYS);
1139     IWineD3DDevice_SetRenderState(device, WINED3DRS_STENCILWRITEMASK, 0xFFFFFFFF);
1140     IWineD3DDevice_SetRenderState(device, WINED3DRS_TEXTUREFACTOR,    0xFFFFFFFF);
1141     IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP0, 0);
1142     IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP1, 0);
1143     IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP2, 0);
1144     IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP3, 0);
1145     IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP4, 0);
1146     IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP5, 0);
1147     IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP6, 0);
1148     IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP7, 0);
1149     IWineD3DDevice_SetRenderState(device, WINED3DRS_CLIPPING,                 TRUE);
1150     IWineD3DDevice_SetRenderState(device, WINED3DRS_LIGHTING,                 TRUE);
1151     IWineD3DDevice_SetRenderState(device, WINED3DRS_AMBIENT,                  0);
1152     IWineD3DDevice_SetRenderState(device, WINED3DRS_FOGVERTEXMODE,            WINED3DFOG_NONE);
1153     IWineD3DDevice_SetRenderState(device, WINED3DRS_COLORVERTEX,              TRUE);
1154     IWineD3DDevice_SetRenderState(device, WINED3DRS_LOCALVIEWER,              TRUE);
1155     IWineD3DDevice_SetRenderState(device, WINED3DRS_NORMALIZENORMALS,         FALSE);
1156     IWineD3DDevice_SetRenderState(device, WINED3DRS_DIFFUSEMATERIALSOURCE,    WINED3DMCS_COLOR1);
1157     IWineD3DDevice_SetRenderState(device, WINED3DRS_SPECULARMATERIALSOURCE,   WINED3DMCS_COLOR2);
1158     IWineD3DDevice_SetRenderState(device, WINED3DRS_AMBIENTMATERIALSOURCE,    WINED3DMCS_MATERIAL);
1159     IWineD3DDevice_SetRenderState(device, WINED3DRS_EMISSIVEMATERIALSOURCE,   WINED3DMCS_MATERIAL);
1160     IWineD3DDevice_SetRenderState(device, WINED3DRS_VERTEXBLEND,              WINED3DVBF_DISABLE);
1161     IWineD3DDevice_SetRenderState(device, WINED3DRS_CLIPPLANEENABLE,          0);
1162     IWineD3DDevice_SetRenderState(device, WINED3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
1163     tmpfloat.f = 1.0f;
1164     IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSIZE,                tmpfloat.d);
1165     tmpfloat.f = ((IWineD3DImpl *)This->wineD3DDevice->wineD3D)->dxVersion < 9 ? 0.0f : 1.0f;
1166     IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSIZE_MIN,            tmpfloat.d);
1167     IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSPRITEENABLE,        FALSE);
1168     IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSCALEENABLE,         FALSE);
1169     tmpfloat.f = 1.0f;
1170     IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSCALE_A,             tmpfloat.d);
1171     tmpfloat.f = 0.0f;
1172     IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSCALE_B,             tmpfloat.d);
1173     tmpfloat.f = 0.0f;
1174     IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSCALE_C,             tmpfloat.d);
1175     IWineD3DDevice_SetRenderState(device, WINED3DRS_MULTISAMPLEANTIALIAS,     TRUE);
1176     IWineD3DDevice_SetRenderState(device, WINED3DRS_MULTISAMPLEMASK,          0xFFFFFFFF);
1177     IWineD3DDevice_SetRenderState(device, WINED3DRS_PATCHEDGESTYLE,           WINED3DPATCHEDGE_DISCRETE);
1178     tmpfloat.f = 1.0f;
1179     IWineD3DDevice_SetRenderState(device, WINED3DRS_PATCHSEGMENTS,            tmpfloat.d);
1180     IWineD3DDevice_SetRenderState(device, WINED3DRS_DEBUGMONITORTOKEN,        0xbaadcafe);
1181     tmpfloat.f = gl_info->max_pointsize;
1182     IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSIZE_MAX,            tmpfloat.d);
1183     IWineD3DDevice_SetRenderState(device, WINED3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
1184     IWineD3DDevice_SetRenderState(device, WINED3DRS_COLORWRITEENABLE,         0x0000000F);
1185     tmpfloat.f = 0.0f;
1186     IWineD3DDevice_SetRenderState(device, WINED3DRS_TWEENFACTOR,              tmpfloat.d);
1187     IWineD3DDevice_SetRenderState(device, WINED3DRS_BLENDOP,                  WINED3DBLENDOP_ADD);
1188     IWineD3DDevice_SetRenderState(device, WINED3DRS_POSITIONDEGREE,           WINED3DDEGREE_CUBIC);
1189     IWineD3DDevice_SetRenderState(device, WINED3DRS_NORMALDEGREE,             WINED3DDEGREE_LINEAR);
1190     /* states new in d3d9 */
1191     IWineD3DDevice_SetRenderState(device, WINED3DRS_SCISSORTESTENABLE,        FALSE);
1192     IWineD3DDevice_SetRenderState(device, WINED3DRS_SLOPESCALEDEPTHBIAS,      0);
1193     tmpfloat.f = 1.0f;
1194     IWineD3DDevice_SetRenderState(device, WINED3DRS_MINTESSELLATIONLEVEL,     tmpfloat.d);
1195     IWineD3DDevice_SetRenderState(device, WINED3DRS_MAXTESSELLATIONLEVEL,     tmpfloat.d);
1196     IWineD3DDevice_SetRenderState(device, WINED3DRS_ANTIALIASEDLINEENABLE,    FALSE);
1197     tmpfloat.f = 0.0f;
1198     IWineD3DDevice_SetRenderState(device, WINED3DRS_ADAPTIVETESS_X,           tmpfloat.d);
1199     IWineD3DDevice_SetRenderState(device, WINED3DRS_ADAPTIVETESS_Y,           tmpfloat.d);
1200     tmpfloat.f = 1.0f;
1201     IWineD3DDevice_SetRenderState(device, WINED3DRS_ADAPTIVETESS_Z,           tmpfloat.d);
1202     tmpfloat.f = 0.0f;
1203     IWineD3DDevice_SetRenderState(device, WINED3DRS_ADAPTIVETESS_W,           tmpfloat.d);
1204     IWineD3DDevice_SetRenderState(device, WINED3DRS_ENABLEADAPTIVETESSELLATION, FALSE);
1205     IWineD3DDevice_SetRenderState(device, WINED3DRS_TWOSIDEDSTENCILMODE,      FALSE);
1206     IWineD3DDevice_SetRenderState(device, WINED3DRS_CCW_STENCILFAIL,          WINED3DSTENCILOP_KEEP);
1207     IWineD3DDevice_SetRenderState(device, WINED3DRS_CCW_STENCILZFAIL,         WINED3DSTENCILOP_KEEP);
1208     IWineD3DDevice_SetRenderState(device, WINED3DRS_CCW_STENCILPASS,          WINED3DSTENCILOP_KEEP);
1209     IWineD3DDevice_SetRenderState(device, WINED3DRS_CCW_STENCILFUNC,          WINED3DCMP_ALWAYS);
1210     IWineD3DDevice_SetRenderState(device, WINED3DRS_COLORWRITEENABLE1,        0x0000000F);
1211     IWineD3DDevice_SetRenderState(device, WINED3DRS_COLORWRITEENABLE2,        0x0000000F);
1212     IWineD3DDevice_SetRenderState(device, WINED3DRS_COLORWRITEENABLE3,        0x0000000F);
1213     IWineD3DDevice_SetRenderState(device, WINED3DRS_BLENDFACTOR,              0xFFFFFFFF);
1214     IWineD3DDevice_SetRenderState(device, WINED3DRS_SRGBWRITEENABLE,          0);
1215     IWineD3DDevice_SetRenderState(device, WINED3DRS_DEPTHBIAS,                0);
1216     IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP8,  0);
1217     IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP9,  0);
1218     IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP10, 0);
1219     IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP11, 0);
1220     IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP12, 0);
1221     IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP13, 0);
1222     IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP14, 0);
1223     IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP15, 0);
1224     IWineD3DDevice_SetRenderState(device, WINED3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1225     IWineD3DDevice_SetRenderState(device, WINED3DRS_SRCBLENDALPHA,            WINED3DBLEND_ONE);
1226     IWineD3DDevice_SetRenderState(device, WINED3DRS_DESTBLENDALPHA,           WINED3DBLEND_ZERO);
1227     IWineD3DDevice_SetRenderState(device, WINED3DRS_BLENDOPALPHA,             WINED3DBLENDOP_ADD);
1228
1229     /* clipping status */
1230     This->clip_status.ClipUnion = 0;
1231     This->clip_status.ClipIntersection = 0xFFFFFFFF;
1232
1233     /* Texture Stage States - Put directly into state block, we will call function below */
1234     for (i = 0; i < MAX_TEXTURES; i++) {
1235         TRACE("Setting up default texture states for texture Stage %d\n", i);
1236         memcpy(&This->transforms[WINED3DTS_TEXTURE0 + i], identity, sizeof(identity));
1237         This->textureState[i][WINED3DTSS_COLOROP               ] = (i==0)? WINED3DTOP_MODULATE :  WINED3DTOP_DISABLE;
1238         This->textureState[i][WINED3DTSS_COLORARG1             ] = WINED3DTA_TEXTURE;
1239         This->textureState[i][WINED3DTSS_COLORARG2             ] = WINED3DTA_CURRENT;
1240         This->textureState[i][WINED3DTSS_ALPHAOP               ] = (i==0)? WINED3DTOP_SELECTARG1 :  WINED3DTOP_DISABLE;
1241         This->textureState[i][WINED3DTSS_ALPHAARG1             ] = WINED3DTA_TEXTURE;
1242         This->textureState[i][WINED3DTSS_ALPHAARG2             ] = WINED3DTA_CURRENT;
1243         This->textureState[i][WINED3DTSS_BUMPENVMAT00          ] = 0;
1244         This->textureState[i][WINED3DTSS_BUMPENVMAT01          ] = 0;
1245         This->textureState[i][WINED3DTSS_BUMPENVMAT10          ] = 0;
1246         This->textureState[i][WINED3DTSS_BUMPENVMAT11          ] = 0;
1247         This->textureState[i][WINED3DTSS_TEXCOORDINDEX         ] = i;
1248         This->textureState[i][WINED3DTSS_BUMPENVLSCALE         ] = 0;
1249         This->textureState[i][WINED3DTSS_BUMPENVLOFFSET        ] = 0;
1250         This->textureState[i][WINED3DTSS_TEXTURETRANSFORMFLAGS ] = WINED3DTTFF_DISABLE;
1251         This->textureState[i][WINED3DTSS_COLORARG0             ] = WINED3DTA_CURRENT;
1252         This->textureState[i][WINED3DTSS_ALPHAARG0             ] = WINED3DTA_CURRENT;
1253         This->textureState[i][WINED3DTSS_RESULTARG             ] = WINED3DTA_CURRENT;
1254     }
1255     This->lowest_disabled_stage = 1;
1256
1257         /* Sampler states*/
1258     for (i = 0 ; i <  MAX_COMBINED_SAMPLERS; i++) {
1259         TRACE("Setting up default samplers states for sampler %d\n", i);
1260         This->samplerState[i][WINED3DSAMP_ADDRESSU         ] = WINED3DTADDRESS_WRAP;
1261         This->samplerState[i][WINED3DSAMP_ADDRESSV         ] = WINED3DTADDRESS_WRAP;
1262         This->samplerState[i][WINED3DSAMP_ADDRESSW         ] = WINED3DTADDRESS_WRAP;
1263         This->samplerState[i][WINED3DSAMP_BORDERCOLOR      ] = 0x00;
1264         This->samplerState[i][WINED3DSAMP_MAGFILTER        ] = WINED3DTEXF_POINT;
1265         This->samplerState[i][WINED3DSAMP_MINFILTER        ] = WINED3DTEXF_POINT;
1266         This->samplerState[i][WINED3DSAMP_MIPFILTER        ] = WINED3DTEXF_NONE;
1267         This->samplerState[i][WINED3DSAMP_MIPMAPLODBIAS    ] = 0;
1268         This->samplerState[i][WINED3DSAMP_MAXMIPLEVEL      ] = 0;
1269         This->samplerState[i][WINED3DSAMP_MAXANISOTROPY    ] = 1;
1270         This->samplerState[i][WINED3DSAMP_SRGBTEXTURE      ] = 0;
1271         This->samplerState[i][WINED3DSAMP_ELEMENTINDEX     ] = 0; /* TODO: Indicates which element of a  multielement texture to use */
1272         This->samplerState[i][WINED3DSAMP_DMAPOFFSET       ] = 0; /* TODO: Vertex offset in the presampled displacement map */
1273     }
1274
1275     for (i = 0; i < gl_info->max_textures; ++i)
1276     {
1277         /* Note: This avoids calling SetTexture, so pretend it has been called */
1278         This->changed.textures |= 1 << i;
1279         This->textures[i]         = NULL;
1280     }
1281
1282     /* check the return values, because the GetBackBuffer call isn't valid for ddraw */
1283     hr = IWineD3DDevice_GetSwapChain(device, 0, &swapchain);
1284     if( hr == WINED3D_OK && swapchain != NULL) {
1285         WINED3DVIEWPORT vp;
1286
1287         hr = IWineD3DSwapChain_GetBackBuffer(swapchain, 0, WINED3DBACKBUFFER_TYPE_MONO, &backbuffer);
1288         if (SUCCEEDED(hr) && backbuffer)
1289         {
1290             WINED3DSURFACE_DESC desc;
1291             RECT scissorrect;
1292
1293             IWineD3DSurface_GetDesc(backbuffer, &desc);
1294             IWineD3DSurface_Release(backbuffer);
1295
1296             /* Set the default scissor rect values */
1297             scissorrect.left = 0;
1298             scissorrect.right = desc.width;
1299             scissorrect.top = 0;
1300             scissorrect.bottom = desc.height;
1301             hr = IWineD3DDevice_SetScissorRect(device, &scissorrect);
1302             if (FAILED(hr)) ERR("This should never happen, expect rendering issues!\n");
1303         }
1304
1305         /* Set the default viewport */
1306         vp.X      = 0;
1307         vp.Y      = 0;
1308         vp.Width  = ((IWineD3DSwapChainImpl *)swapchain)->presentParms.BackBufferWidth;
1309         vp.Height = ((IWineD3DSwapChainImpl *)swapchain)->presentParms.BackBufferHeight;
1310         vp.MinZ   = 0.0f;
1311         vp.MaxZ   = 1.0f;
1312         IWineD3DDevice_SetViewport(device, &vp);
1313
1314         IWineD3DSwapChain_Release(swapchain);
1315     }
1316
1317     TRACE("-----------------------> Device defaults now set up...\n");
1318     return WINED3D_OK;
1319 }
1320
1321 /**********************************************************
1322  * IWineD3DStateBlock VTbl follows
1323  **********************************************************/
1324
1325 static const IWineD3DStateBlockVtbl IWineD3DStateBlock_Vtbl =
1326 {
1327     /* IUnknown */
1328     IWineD3DStateBlockImpl_QueryInterface,
1329     IWineD3DStateBlockImpl_AddRef,
1330     IWineD3DStateBlockImpl_Release,
1331     /* IWineD3DStateBlock */
1332     IWineD3DStateBlockImpl_GetParent,
1333     IWineD3DStateBlockImpl_GetDevice,
1334     IWineD3DStateBlockImpl_Capture,
1335     IWineD3DStateBlockImpl_Apply,
1336     IWineD3DStateBlockImpl_InitStartupStateBlock
1337 };
1338
1339 HRESULT stateblock_init(IWineD3DStateBlockImpl *stateblock, IWineD3DDeviceImpl *device,
1340         WINED3DSTATEBLOCKTYPE type, IUnknown *parent)
1341 {
1342     unsigned int i;
1343     HRESULT hr;
1344
1345     stateblock->lpVtbl = &IWineD3DStateBlock_Vtbl;
1346     stateblock->ref = 1;
1347     stateblock->parent = parent;
1348     stateblock->wineD3DDevice = device;
1349     stateblock->blockType = type;
1350
1351     for (i = 0; i < LIGHTMAP_SIZE; i++)
1352     {
1353         list_init(&stateblock->lightMap[i]);
1354     }
1355
1356     hr = stateblock_allocate_shader_constants(stateblock);
1357     if (FAILED(hr)) return hr;
1358
1359     /* The WINED3DSBT_INIT stateblock type is used during initialization to
1360      * produce a placeholder stateblock so other functions called can update a
1361      * state block. */
1362     if (type == WINED3DSBT_INIT || type == WINED3DSBT_RECORDED) return WINED3D_OK;
1363
1364     TRACE("Updating changed flags appropriate for type %#x.\n", type);
1365
1366     switch (type)
1367     {
1368         case WINED3DSBT_ALL:
1369             stateblock_init_lights(stateblock, device->stateBlock->lightMap);
1370             stateblock_savedstates_set_all(&stateblock->changed, device->d3d_vshader_constantF,
1371                                            device->d3d_pshader_constantF);
1372             break;
1373
1374         case WINED3DSBT_PIXELSTATE:
1375             stateblock_savedstates_set_pixel(&stateblock->changed, device->d3d_pshader_constantF);
1376             break;
1377
1378         case WINED3DSBT_VERTEXSTATE:
1379             stateblock_init_lights(stateblock, device->stateBlock->lightMap);
1380             stateblock_savedstates_set_vertex(&stateblock->changed, device->d3d_vshader_constantF);
1381             break;
1382
1383         default:
1384             FIXME("Unrecognized state block type %#x.\n", type);
1385             break;
1386     }
1387
1388     stateblock_init_contained_states(stateblock);
1389     IWineD3DStateBlockImpl_Capture((IWineD3DStateBlock *)stateblock);
1390
1391     return WINED3D_OK;
1392 }