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