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