Added 'wine' prefix to libwine_unicode exports.
[wine] / dlls / d3d8 / stateblock.c
1 /*
2  * state block implementation
3  *
4  * Copyright 2002 Raphael Junqueira
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "windef.h"
22 #include "winbase.h"
23 #include "winuser.h"
24 #include "wingdi.h"
25 #include "wine/debug.h"
26
27 #include <math.h>
28
29 #include "d3d8_private.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
32
33 /* Used for CreateStateBlock */
34 #define NUM_SAVEDPIXELSTATES_R     38
35 #define NUM_SAVEDPIXELSTATES_T     27
36 #define NUM_SAVEDVERTEXSTATES_R    33
37 #define NUM_SAVEDVERTEXSTATES_T    2
38
39 /*
40  * Globals
41  */
42 extern DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R];
43 extern DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T];
44 extern DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R];
45 extern DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T];
46 static const float idmatrix[16] = {
47   1.0, 0.0, 0.0, 0.0,
48   0.0, 1.0, 0.0, 0.0,
49   0.0, 0.0, 1.0, 0.0,
50   0.0, 0.0, 0.0, 1.0
51 };
52
53 HRESULT WINAPI IDirect3DDeviceImpl_InitStartupStateBlock(IDirect3DDevice8Impl* This) {
54     D3DLINEPATTERN lp;
55     int i;
56     LPDIRECT3DDEVICE8 iface = (LPDIRECT3DDEVICE8) This;
57
58     /* Note this may have a large overhead but it should only be executed
59        once, in order to initialize the complete state of the device and 
60        all opengl equivalents                                            */
61     TRACE("-----------------------> Setting up device defaults...\n");
62     This->StateBlock->blockType = D3DSBT_ALL;
63
64     /* FIXME: Set some of the defaults for lights, transforms etc */
65     memcpy(&This->StateBlock->transforms[D3DTS_PROJECTION], &idmatrix, sizeof(idmatrix));
66     memcpy(&This->StateBlock->transforms[D3DTS_VIEW], &idmatrix, sizeof(idmatrix));
67     for (i = 0; i < 256; ++i) {
68       memcpy(&This->StateBlock->transforms[D3DTS_WORLDMATRIX(i)], &idmatrix, sizeof(idmatrix));
69     }
70  
71     /* Render states: */
72     if (This->PresentParms.EnableAutoDepthStencil) {
73        IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ZENABLE, D3DZB_TRUE);
74     } else {
75        IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ZENABLE, D3DZB_FALSE);
76     }
77     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_FILLMODE, D3DFILL_SOLID);
78     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
79     lp.wRepeatFactor = 0; lp.wLinePattern = 0; IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_LINEPATTERN, (DWORD) &lp);
80     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ZWRITEENABLE, TRUE);
81     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ALPHATESTENABLE, FALSE);
82     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_LASTPIXEL, TRUE);
83     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_SRCBLEND, D3DBLEND_ONE);
84     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_DESTBLEND, D3DBLEND_ZERO);
85     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_CULLMODE, D3DCULL_CCW);
86     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
87     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ALPHAFUNC, D3DCMP_ALWAYS);
88     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ALPHAREF, 0xff); /*??*/
89     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_DITHERENABLE, FALSE);
90     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ALPHABLENDENABLE, FALSE);
91     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_FOGENABLE, FALSE);
92     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_SPECULARENABLE, FALSE);
93     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ZVISIBLE, 0);
94     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_FOGCOLOR, 0);
95     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
96     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_FOGSTART, 0.0f);
97     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_FOGEND, 1.0f);
98     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_FOGDENSITY, 1.0f);
99     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_EDGEANTIALIAS, FALSE);
100     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ZBIAS, 0);
101     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_RANGEFOGENABLE, FALSE);
102     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILENABLE, FALSE);
103     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
104     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
105     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
106     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
107     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILREF, 0);
108     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILMASK, 0xFFFFFFFF);
109     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILWRITEMASK, 0xFFFFFFFF);
110     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_TEXTUREFACTOR, 0xFFFFFFFF);
111     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_WRAP0, 0);
112     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_WRAP1, 0);
113     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_WRAP2, 0);
114     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_WRAP3, 0);
115     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_WRAP4, 0);
116     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_WRAP5, 0);
117     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_WRAP6, 0);
118     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_WRAP7, 0);
119     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_CLIPPING, TRUE);
120     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_LIGHTING, TRUE);
121     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_AMBIENT, 0);
122     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
123     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_COLORVERTEX, TRUE);
124     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_LOCALVIEWER, TRUE);
125     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_NORMALIZENORMALS, FALSE);
126     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
127     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
128     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR2);
129     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
130     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_VERTEXBLEND, D3DVBF_DISABLE);
131     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_CLIPPLANEENABLE, 0);
132     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
133     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POINTSIZE, 1.0f);
134     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POINTSIZE_MIN, 0.0f);
135     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POINTSPRITEENABLE, FALSE);
136     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POINTSCALEENABLE, FALSE);
137     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POINTSCALE_A, TRUE);
138     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POINTSCALE_B, TRUE);
139     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POINTSCALE_C, TRUE);
140     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_MULTISAMPLEANTIALIAS, TRUE);
141     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
142     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE);
143     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_PATCHSEGMENTS, 1.0f);
144     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_DEBUGMONITORTOKEN, D3DDMT_DISABLE);
145     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POINTSIZE_MAX, (DWORD) 64.0f);
146     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
147     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_COLORWRITEENABLE, 0x0000000F);
148     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_TWEENFACTOR, (DWORD) 0.0f);
149     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_BLENDOP, D3DBLENDOP_ADD);
150     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POSITIONORDER, D3DORDER_CUBIC);
151     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_NORMALORDER, D3DORDER_LINEAR);
152
153     /* Texture Stage States - Put directly into state block, we will call function below */
154     for (i=0; i<This->TextureUnits;i++) {
155         memcpy(&This->StateBlock->transforms[D3DTS_TEXTURE0+i], &idmatrix, sizeof(idmatrix));
156         This->StateBlock->texture_state[i][D3DTSS_COLOROP               ] = (i==0)? D3DTOP_MODULATE :  D3DTOP_DISABLE;
157         This->StateBlock->texture_state[i][D3DTSS_COLORARG1             ] = D3DTA_TEXTURE;
158         This->StateBlock->texture_state[i][D3DTSS_COLORARG2             ] = D3DTA_CURRENT;
159         This->StateBlock->texture_state[i][D3DTSS_ALPHAOP               ] = (i==0)? D3DTOP_SELECTARG1 :  D3DTOP_DISABLE;
160         This->StateBlock->texture_state[i][D3DTSS_ALPHAARG1             ] = D3DTA_TEXTURE;
161         This->StateBlock->texture_state[i][D3DTSS_ALPHAARG2             ] = D3DTA_CURRENT;
162         This->StateBlock->texture_state[i][D3DTSS_BUMPENVMAT00          ] = (DWORD) 0.0;
163         This->StateBlock->texture_state[i][D3DTSS_BUMPENVMAT01          ] = (DWORD) 0.0;
164         This->StateBlock->texture_state[i][D3DTSS_BUMPENVMAT10          ] = (DWORD) 0.0;
165         This->StateBlock->texture_state[i][D3DTSS_BUMPENVMAT11          ] = (DWORD) 0.0;
166         /* FIXME: This->StateBlock->texture_state[i][D3DTSS_TEXCOORDINDEX         ] = ?; */
167         This->StateBlock->texture_state[i][D3DTSS_ADDRESSU              ] = D3DTADDRESS_WRAP;
168         This->StateBlock->texture_state[i][D3DTSS_ADDRESSV              ] = D3DTADDRESS_WRAP;
169         This->StateBlock->texture_state[i][D3DTSS_BORDERCOLOR           ] = 0x00;
170         This->StateBlock->texture_state[i][D3DTSS_MAGFILTER             ] = D3DTEXF_POINT;
171         This->StateBlock->texture_state[i][D3DTSS_MINFILTER             ] = D3DTEXF_POINT;
172         This->StateBlock->texture_state[i][D3DTSS_MIPFILTER             ] = D3DTEXF_NONE;
173         This->StateBlock->texture_state[i][D3DTSS_MIPMAPLODBIAS         ] = 0;
174         This->StateBlock->texture_state[i][D3DTSS_MAXMIPLEVEL           ] = 0;
175         This->StateBlock->texture_state[i][D3DTSS_MAXANISOTROPY         ] = 1;
176         This->StateBlock->texture_state[i][D3DTSS_BUMPENVLSCALE         ] = (DWORD) 0.0;
177         This->StateBlock->texture_state[i][D3DTSS_BUMPENVLOFFSET        ] = (DWORD) 0.0;
178         This->StateBlock->texture_state[i][D3DTSS_TEXTURETRANSFORMFLAGS ] = D3DTTFF_DISABLE;
179         This->StateBlock->texture_state[i][D3DTSS_ADDRESSW              ] = D3DTADDRESS_WRAP;
180         This->StateBlock->texture_state[i][D3DTSS_COLORARG0             ] = D3DTA_CURRENT;
181         This->StateBlock->texture_state[i][D3DTSS_ALPHAARG0             ] = D3DTA_CURRENT;
182         This->StateBlock->texture_state[i][D3DTSS_RESULTARG             ] = D3DTA_CURRENT;
183     }
184
185     /* Under DirectX you can have texture stage operations even if no texture is
186        bound, whereas opengl will only do texture operations when a valid texture is
187        bound. We emulate this by creating dummy textures and binding them to each
188        texture stage, but disable all stages by default. Hence if a stage is enabled
189        then the default texture will kick in until replaced by a SetTexture call     */
190
191     for (i = 0; i < This->TextureUnits; i++) {
192         GLubyte white = 255;
193
194         /* Note this avoids calling settexture, so pretend it has been called */
195         This->StateBlock->Set.textures[i] = TRUE;
196         This->StateBlock->Changed.textures[i] = TRUE;
197         This->StateBlock->textures[i] = NULL;
198
199         /* Make appropriate texture active */
200         if (This->isMultiTexture) {
201             glActiveTextureARB(GL_TEXTURE0_ARB + i);
202             checkGLcall("glActiveTextureARB");
203         } else if (i>0) {
204             FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
205         }
206
207         /* Generate an opengl texture name */
208         glGenTextures(1, &This->dummyTextureName[i]);
209         checkGLcall("glGenTextures");
210         TRACE("Dummy Texture %d given name %d\n", i, This->dummyTextureName[i]);
211
212         /* Generate a dummy 1d texture */
213         This->StateBlock->textureDimensions[i] = GL_TEXTURE_1D;
214         glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
215         checkGLcall("glBindTexture");
216
217         glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &white); 
218         checkGLcall("glTexImage1D");
219
220         /* Reapply all the texture state information to this texture */
221         setupTextureStates(iface, i);
222     }
223
224     TRACE("-----------------------> Device defaults now set up...\n");
225
226     return D3D_OK;
227 }
228
229
230
231 HRESULT WINAPI IDirect3DDeviceImpl_CreateStateBlock(IDirect3DDevice8Impl* This, D3DSTATEBLOCKTYPE Type, IDirect3DStateBlockImpl** ppStateBlock) {
232   IDirect3DStateBlockImpl* object;
233   UINT i, j;
234
235   TRACE("(%p) : Type(%d)\n", This, Type);
236
237   /* Allocate Storage */
238   object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DStateBlockImpl));
239   if (object) {
240     if (NULL == This->StateBlock) { /** if it the main stateblock only do init and returns */
241       /*object->lpVtbl = &Direct3DStateBlock9_Vtbl;*/
242       object->device = This; /* FIXME: AddRef(This) */
243       object->ref = 1;
244       object->blockType = Type;
245       This->StateBlock = object;
246       /* don't forget to init it calling InitStartupStateBlock */
247       return D3D_OK;
248     }
249     memcpy(object, This->StateBlock, sizeof(IDirect3DStateBlockImpl));
250   } else {
251     *ppStateBlock = (IDirect3DStateBlockImpl*) 0xFFFFFFFF;
252     return E_OUTOFMEMORY;
253   }
254   /*object->lpVtbl = &Direct3DStateBlock9_Vtbl;*/
255   object->device = This; /* FIXME: AddRef(This) */
256   object->ref = 1;
257   object->blockType = Type;
258
259   TRACE("Updating changed flags appropriate for type %d\n", Type);
260
261   if (Type == D3DSBT_ALL) {
262     TRACE("ALL => Pretend everything has changed\n");
263     memset(&object->Changed, TRUE, sizeof(This->StateBlock->Changed));
264     
265   } else if (Type == D3DSBT_PIXELSTATE) {
266     
267     memset(&object->Changed, FALSE, sizeof(This->StateBlock->Changed));
268     
269     /* TODO: Pixel Shader Constants */
270     object->Changed.pixelShader = TRUE;
271     for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
272       object->Changed.renderstate[SavedPixelStates_R[i]] = TRUE;
273     }
274     for (j = 0; j < This->TextureUnits; i++) {
275       for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
276         object->Changed.texture_state[j][SavedPixelStates_T[i]] = TRUE;
277       }
278     }
279     
280   } else if (Type == D3DSBT_VERTEXSTATE) {
281     
282     memset(&object->Changed, FALSE, sizeof(This->StateBlock->Changed));
283     
284     /* TODO: Vertex Shader Constants */
285     object->Changed.vertexShader = TRUE;
286     for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
287       object->Changed.renderstate[SavedVertexStates_R[i]] = TRUE;
288     }
289     for (j = 0; j < This->TextureUnits; i++) {
290       for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
291         object->Changed.texture_state[j][SavedVertexStates_T[i]] = TRUE;
292       }
293     }
294     for (i = 0; i < This->maxLights; i++) {
295       object->Changed.lightEnable[i] = TRUE;
296       object->Changed.lights[i] = TRUE;
297     }
298     
299   } else {
300     FIXME("Unrecognized state block type %d\n", Type);
301   }
302   TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
303   
304   *ppStateBlock = object;
305   return D3D_OK;
306 }
307
308 /** yakkk temporary waiting for Release */
309 HRESULT WINAPI IDirect3DDeviceImpl_DeleteStateBlock(IDirect3DDevice8Impl* This, IDirect3DStateBlockImpl* pSB) {
310   TRACE("(%p) : freeing StateBlock %p\n", This, pSB);
311   HeapFree(GetProcessHeap(), 0, (void *)pSB);
312   return D3D_OK;
313 }
314
315 HRESULT WINAPI IDirect3DDeviceImpl_BeginStateBlock(IDirect3DDevice8Impl* This) {
316   IDirect3DStateBlockImpl* object;
317   
318   TRACE("(%p)\n", This);
319   
320   if (This->isRecordingState) {
321     TRACE("(%p) already recording! returning error\n", This);
322     return D3DERR_INVALIDCALL;
323   }
324
325   /* Allocate Storage */
326   object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DStateBlockImpl));
327   if (object) {
328   } else {
329     return E_OUTOFMEMORY;
330   }
331   /*object->lpVtbl = &Direct3DVextexShaderDeclaration8_Vtbl;*/
332   object->device = This; /* FIXME: AddRef(This) */
333   object->ref = 1;
334   
335   This->isRecordingState = TRUE;
336   This->UpdateStateBlock = object;
337   
338   return D3D_OK;
339 }
340
341 HRESULT WINAPI IDirect3DDeviceImpl_EndStateBlock(IDirect3DDevice8Impl* This, IDirect3DStateBlockImpl** ppStateBlock) {
342   TRACE("(%p)\n", This);
343   
344   if (!This->isRecordingState) {
345     TRACE("(%p) not recording! returning error\n", This);
346     *ppStateBlock = NULL;
347     return D3DERR_INVALIDCALL;
348   }
349
350   This->UpdateStateBlock->blockType = D3DSBT_RECORDED;
351   *ppStateBlock = This->UpdateStateBlock;
352   This->isRecordingState = FALSE;
353   This->UpdateStateBlock = This->StateBlock;
354   
355   TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
356   return D3D_OK;
357 }
358
359 HRESULT  WINAPI  IDirect3DDeviceImpl_ApplyStateBlock(IDirect3DDevice8Impl* This, IDirect3DStateBlockImpl* pSB) {
360     UINT i;
361     UINT j;
362     LPDIRECT3DDEVICE8 iface = (LPDIRECT3DDEVICE8) This;
363
364     TRACE("(%p) : Applying state block %p ------------------v\n", This, pSB);
365
366     /* FIXME: Only apply applicable states not all states */
367
368     if (pSB->blockType == D3DSBT_RECORDED || pSB->blockType == D3DSBT_ALL || pSB->blockType == D3DSBT_VERTEXSTATE) {
369
370         for (i=0; i<This->maxLights; i++) {
371
372             if (pSB->Set.lightEnable[i] && pSB->Changed.lightEnable[i])
373                 IDirect3DDevice8Impl_LightEnable(iface, i, pSB->lightEnable[i]);
374             if (pSB->Set.lights[i] && pSB->Changed.lights[i])
375                 IDirect3DDevice8Impl_SetLight(iface, i, &pSB->lights[i]);
376         }
377
378         if (pSB->Set.vertexShader && pSB->Changed.vertexShader)
379             IDirect3DDevice8Impl_SetVertexShader(iface, pSB->VertexShader);
380
381         /* TODO: Vertex Shader Constants */
382     }
383
384     if (pSB->blockType == D3DSBT_RECORDED || pSB->blockType == D3DSBT_ALL || pSB->blockType == D3DSBT_PIXELSTATE) {
385
386         if (pSB->Set.pixelShader && pSB->Changed.pixelShader)
387             IDirect3DDevice8Impl_SetPixelShader(iface, pSB->PixelShader);
388
389         /* TODO: Pixel Shader Constants */
390     }
391
392     /* Others + Render & Texture */
393     if (pSB->blockType == D3DSBT_RECORDED || pSB->blockType == D3DSBT_ALL) {
394         for (i=0; i<HIGHEST_TRANSFORMSTATE; i++) {
395             if (pSB->Set.transform[i] && pSB->Changed.transform[i])
396                 IDirect3DDevice8Impl_SetTransform(iface, i, &pSB->transforms[i]);
397         }
398
399         if (pSB->Set.Indices && pSB->Changed.Indices)
400             IDirect3DDevice8Impl_SetIndices(iface, pSB->pIndexData, pSB->baseVertexIndex);
401
402         if (pSB->Set.material && pSB->Changed.material)
403             IDirect3DDevice8Impl_SetMaterial(iface, &pSB->material);
404
405         if (pSB->Set.viewport && pSB->Changed.viewport)
406             IDirect3DDevice8Impl_SetViewport(iface, &pSB->viewport);
407
408         for (i=0; i<MAX_STREAMS; i++) {
409             if (pSB->Set.stream_source[i] && pSB->Changed.stream_source[i])
410                 IDirect3DDevice8Impl_SetStreamSource(iface, i, pSB->stream_source[i], pSB->stream_stride[i]);
411         }
412
413         for (i=0; i<This->clipPlanes; i++) {
414             if (pSB->Set.clipplane[i] && pSB->Changed.clipplane[i]) {
415                 float clip[4];
416
417                 clip[0] = pSB->clipplane[i][0];
418                 clip[1] = pSB->clipplane[i][1];
419                 clip[2] = pSB->clipplane[i][2];
420                 clip[3] = pSB->clipplane[i][3];
421                 IDirect3DDevice8Impl_SetClipPlane(iface, i, clip);
422             }
423         }
424
425         /* Render */
426         for (i=0; i<HIGHEST_RENDER_STATE; i++) {
427
428             if (pSB->Set.renderstate[i] && pSB->Changed.renderstate[i])
429                 IDirect3DDevice8Impl_SetRenderState(iface, i, pSB->renderstate[i]);
430
431         }
432
433         /* Texture */
434         for (j = 0; j < This->TextureUnits; j++) {
435           for (i = 0; i < HIGHEST_TEXTURE_STATE; i++) {
436             if (pSB->Set.texture_state[j][i] && pSB->Changed.texture_state[j][i]) {
437               IDirect3DDevice8Impl_SetTextureStageState(iface, j, i, pSB->texture_state[j][i]);
438             }
439           } 
440           if (pSB->Set.textures[j] && pSB->Changed.textures[j]) {
441             IDirect3DDevice8Impl_SetTexture(iface, j, pSB->textures[j]);
442           } 
443         }
444
445
446     } else if (pSB->blockType == D3DSBT_PIXELSTATE) {
447
448         for (i=0; i<NUM_SAVEDPIXELSTATES_R; i++) {
449             if (pSB->Set.renderstate[SavedPixelStates_R[i]] && pSB->Changed.renderstate[SavedPixelStates_R[i]])
450                 IDirect3DDevice8Impl_SetRenderState(iface, SavedPixelStates_R[i], pSB->renderstate[SavedPixelStates_R[i]]);
451
452         }
453
454         for (j=0; j<This->TextureUnits; i++) {
455             for (i=0; i<NUM_SAVEDPIXELSTATES_T; i++) {
456
457                 if (pSB->Set.texture_state[j][SavedPixelStates_T[i]] &&
458                     pSB->Changed.texture_state[j][SavedPixelStates_T[i]])
459                     IDirect3DDevice8Impl_SetTextureStageState(iface, j, SavedPixelStates_T[i], pSB->texture_state[j][SavedPixelStates_T[i]]);
460             }
461         }
462
463     } else if (pSB->blockType == D3DSBT_VERTEXSTATE) {
464
465         for (i=0; i<NUM_SAVEDVERTEXSTATES_R; i++) {
466             if (pSB->Set.renderstate[SavedVertexStates_R[i]] && pSB->Changed.renderstate[SavedVertexStates_R[i]])
467                 IDirect3DDevice8Impl_SetRenderState(iface, SavedVertexStates_R[i], pSB->renderstate[SavedVertexStates_R[i]]);
468
469         }
470
471         for (j=0; j<This->TextureUnits; i++) {
472             for (i=0; i<NUM_SAVEDVERTEXSTATES_T; i++) {
473
474                 if (pSB->Set.texture_state[j][SavedVertexStates_T[i]] &&
475                     pSB->Changed.texture_state[j][SavedVertexStates_T[i]])
476                     IDirect3DDevice8Impl_SetTextureStageState(iface, j, SavedVertexStates_T[i], pSB->texture_state[j][SavedVertexStates_T[i]]);
477             }
478         }
479
480
481     } else {
482         FIXME("Unrecognized state block type %d\n", pSB->blockType);
483     }
484     memcpy(&This->StateBlock->Changed, &pSB->Changed, sizeof(This->StateBlock->Changed));
485     TRACE("(%p) : Applied state block %p ------------------^\n", This, pSB);
486
487     return D3D_OK;
488 }
489
490 HRESULT WINAPI IDirect3DDeviceImpl_CaptureStateBlock(IDirect3DDevice8Impl* This, IDirect3DStateBlockImpl* updateBlock) {
491     LPDIRECT3DDEVICE8 iface = (LPDIRECT3DDEVICE8) This;
492
493     TRACE("(%p) : Updating state block %p ------------------v \n", This, updateBlock);
494
495     /* If not recorded, then update can just recapture */
496     if (updateBlock->blockType != D3DSBT_RECORDED) {
497         IDirect3DStateBlockImpl* tmpBlock;
498         IDirect3DDeviceImpl_CreateStateBlock(This, updateBlock->blockType, &tmpBlock);
499         memcpy(updateBlock, tmpBlock, sizeof(IDirect3DStateBlockImpl));
500         IDirect3DDeviceImpl_DeleteStateBlock(This, tmpBlock);
501
502         /* FIXME: This will record states of new lights! May need to have and save set_lights
503            across this action */
504
505     } else {
506         int i,j;
507
508         /* Recorded => Only update 'changed' values */
509         if (updateBlock->Set.vertexShader && updateBlock->VertexShader != This->StateBlock->VertexShader) {
510             updateBlock->VertexShader = This->StateBlock->VertexShader;
511             TRACE("Updating vertex shader to %ld\n", This->StateBlock->VertexShader);
512         }
513
514         /* TODO: Vertex Shader Constants */
515
516         for (i=0; i<This->maxLights; i++) {
517           if (updateBlock->Set.lightEnable[i] && This->StateBlock->lightEnable[i] != updateBlock->lightEnable[i]) {
518               TRACE("Updating light enable for light %d to %d\n", i, This->StateBlock->lightEnable[i]);
519               updateBlock->lightEnable[i] = This->StateBlock->lightEnable[i];
520           }
521
522           if (updateBlock->Set.lights[i] && memcmp(&This->StateBlock->lights[i], 
523                                                    &updateBlock->lights[i], 
524                                                    sizeof(D3DLIGHT8)) != 0) {
525               TRACE("Updating lights for light %d\n", i);
526               memcpy(&updateBlock->lights[i], &This->StateBlock->lights[i], sizeof(D3DLIGHT8));
527           }
528         }
529
530         if (updateBlock->Set.pixelShader && updateBlock->PixelShader != This->StateBlock->PixelShader) {
531             TRACE("Updating pixel shader to %ld\n", This->StateBlock->PixelShader);
532             updateBlock->lights[i] = This->StateBlock->lights[i];
533             IDirect3DDevice8Impl_SetVertexShader(iface, updateBlock->PixelShader);
534         }
535
536         /* TODO: Pixel Shader Constants */
537
538         /* Others + Render & Texture */
539         for (i=0; i<HIGHEST_TRANSFORMSTATE; i++) {
540           if (updateBlock->Set.transform[i] && memcmp(&This->StateBlock->transforms[i], 
541                                                       &updateBlock->transforms[i], 
542                                                       sizeof(D3DMATRIX)) != 0) {
543             TRACE("Updating transform %d\n", i);
544             memcpy(&updateBlock->transforms[i], &This->StateBlock->transforms[i], sizeof(D3DMATRIX));
545           }
546         }
547
548         if (updateBlock->Set.Indices && ((updateBlock->pIndexData != This->StateBlock->pIndexData)
549                                          || (updateBlock->baseVertexIndex != This->StateBlock->baseVertexIndex))) {
550           TRACE("Updating pindexData to %p, baseVertexIndex to %d\n", 
551                 This->StateBlock->pIndexData, This->StateBlock->baseVertexIndex);
552           updateBlock->pIndexData = This->StateBlock->pIndexData;
553           updateBlock->baseVertexIndex = This->StateBlock->baseVertexIndex;
554         }
555
556        if (updateBlock->Set.material && memcmp(&This->StateBlock->material, 
557                                                    &updateBlock->material, 
558                                                    sizeof(D3DMATERIAL8)) != 0) {
559                 TRACE("Updating material\n");
560                 memcpy(&updateBlock->material, &This->StateBlock->material, sizeof(D3DMATERIAL8));
561        }
562            
563        if (updateBlock->Set.viewport && memcmp(&This->StateBlock->viewport, 
564                                                    &updateBlock->viewport, 
565                                                    sizeof(D3DVIEWPORT8)) != 0) {
566                 TRACE("Updating viewport\n");
567                 memcpy(&updateBlock->viewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
568        }
569
570        for (i=0; i<MAX_STREAMS; i++) {
571            if (updateBlock->Set.stream_source[i] && 
572                            ((updateBlock->stream_stride[i] != This->StateBlock->stream_stride[i]) ||
573                            (updateBlock->stream_source[i] != This->StateBlock->stream_source[i]))) {
574                TRACE("Updating stream source %d to %p, stride to %d\n", i, This->StateBlock->stream_source[i], 
575                                                                         This->StateBlock->stream_stride[i]);
576                updateBlock->stream_stride[i] = This->StateBlock->stream_stride[i];
577                updateBlock->stream_source[i] = This->StateBlock->stream_source[i];
578            }
579        }
580
581        for (i=0; i<This->clipPlanes; i++) {
582            if (updateBlock->Set.clipplane[i] && memcmp(&This->StateBlock->clipplane[i], 
583                                                        &updateBlock->clipplane[i], 
584                                                        sizeof(updateBlock->clipplane)) != 0) {
585
586                TRACE("Updating clipplane %d\n", i);
587                memcpy(&updateBlock->clipplane[i], &This->StateBlock->clipplane[i], 
588                                        sizeof(updateBlock->clipplane));
589            }
590        }
591
592        /* Render */
593        for (i=0; i<HIGHEST_RENDER_STATE; i++) {
594
595            if (updateBlock->Set.renderstate[i] && (updateBlock->renderstate[i] != 
596                                                        This->StateBlock->renderstate[i])) {
597                TRACE("Updating renderstate %d to %ld\n", i, This->StateBlock->renderstate[i]);
598                updateBlock->renderstate[i] = This->StateBlock->renderstate[i];
599            }
600        }
601
602        /* Texture */
603        for (j=0; j<This->TextureUnits; j++) {
604            for (i=0; i<HIGHEST_TEXTURE_STATE; i++) {
605
606                if (updateBlock->Set.texture_state[j][i] && (updateBlock->texture_state[j][i] != 
607                                                                 This->StateBlock->texture_state[j][i])) {
608                    TRACE("Updating texturestagestate %d,%d to %ld (was %ld)\n", j,i, This->StateBlock->texture_state[j][i], 
609                                updateBlock->texture_state[j][i]);
610                    updateBlock->texture_state[j][i] =  This->StateBlock->texture_state[j][i];
611                }
612
613                if (updateBlock->Set.textures[j] && (updateBlock->textures[j] != This->StateBlock->textures[j])) {
614                    TRACE("Updating texture %d to %p (was %p)\n", j, This->StateBlock->textures[j],  updateBlock->textures[j]);
615                    updateBlock->textures[j] =  This->StateBlock->textures[j];
616                }
617            }
618
619        }
620     }
621
622     TRACE("(%p) : Updated state block %p ------------------^\n", This, updateBlock);
623
624     return D3D_OK;
625 }
626
627 DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
628     D3DRS_ALPHABLENDENABLE   ,
629     D3DRS_ALPHAFUNC          ,
630     D3DRS_ALPHAREF           ,
631     D3DRS_ALPHATESTENABLE    ,
632     D3DRS_BLENDOP            ,
633     D3DRS_COLORWRITEENABLE   ,
634     D3DRS_DESTBLEND          ,
635     D3DRS_DITHERENABLE       ,
636     D3DRS_EDGEANTIALIAS      ,
637     D3DRS_FILLMODE           ,
638     D3DRS_FOGDENSITY         ,
639     D3DRS_FOGEND             ,
640     D3DRS_FOGSTART           ,
641     D3DRS_LASTPIXEL          ,
642     D3DRS_LINEPATTERN        ,
643     D3DRS_SHADEMODE          ,
644     D3DRS_SRCBLEND           ,
645     D3DRS_STENCILENABLE      ,
646     D3DRS_STENCILFAIL        ,
647     D3DRS_STENCILFUNC        ,
648     D3DRS_STENCILMASK        ,
649     D3DRS_STENCILPASS        ,
650     D3DRS_STENCILREF         ,
651     D3DRS_STENCILWRITEMASK   ,
652     D3DRS_STENCILZFAIL       ,
653     D3DRS_TEXTUREFACTOR      ,
654     D3DRS_WRAP0              ,
655     D3DRS_WRAP1              ,
656     D3DRS_WRAP2              ,
657     D3DRS_WRAP3              ,
658     D3DRS_WRAP4              ,
659     D3DRS_WRAP5              ,
660     D3DRS_WRAP6              ,
661     D3DRS_WRAP7              ,
662     D3DRS_ZBIAS              ,
663     D3DRS_ZENABLE            ,
664     D3DRS_ZFUNC              ,
665     D3DRS_ZWRITEENABLE
666 };
667
668 DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
669     D3DTSS_ADDRESSU              ,
670     D3DTSS_ADDRESSV              ,
671     D3DTSS_ADDRESSW              ,
672     D3DTSS_ALPHAARG0             ,
673     D3DTSS_ALPHAARG1             ,
674     D3DTSS_ALPHAARG2             ,
675     D3DTSS_ALPHAOP               ,
676     D3DTSS_BORDERCOLOR           ,
677     D3DTSS_BUMPENVLOFFSET        ,
678     D3DTSS_BUMPENVLSCALE         ,
679     D3DTSS_BUMPENVMAT00          ,
680     D3DTSS_BUMPENVMAT01          ,
681     D3DTSS_BUMPENVMAT10          ,
682     D3DTSS_BUMPENVMAT11          ,
683     D3DTSS_COLORARG0             ,
684     D3DTSS_COLORARG1             ,
685     D3DTSS_COLORARG2             ,
686     D3DTSS_COLOROP               ,
687     D3DTSS_MAGFILTER             ,
688     D3DTSS_MAXANISOTROPY         ,
689     D3DTSS_MAXMIPLEVEL           ,
690     D3DTSS_MINFILTER             ,
691     D3DTSS_MIPFILTER             ,
692     D3DTSS_MIPMAPLODBIAS         ,
693     D3DTSS_RESULTARG             ,
694     D3DTSS_TEXCOORDINDEX         ,
695     D3DTSS_TEXTURETRANSFORMFLAGS
696 };
697
698 DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
699     D3DRS_AMBIENT                       ,
700     D3DRS_AMBIENTMATERIALSOURCE         ,
701     D3DRS_CLIPPING                      ,
702     D3DRS_CLIPPLANEENABLE               ,
703     D3DRS_COLORVERTEX                   ,
704     D3DRS_DIFFUSEMATERIALSOURCE         ,
705     D3DRS_EMISSIVEMATERIALSOURCE        ,
706     D3DRS_FOGDENSITY                    ,
707     D3DRS_FOGEND                        ,
708     D3DRS_FOGSTART                      ,
709     D3DRS_FOGTABLEMODE                  ,
710     D3DRS_FOGVERTEXMODE                 ,
711     D3DRS_INDEXEDVERTEXBLENDENABLE      ,
712     D3DRS_LIGHTING                      ,
713     D3DRS_LOCALVIEWER                   ,
714     D3DRS_MULTISAMPLEANTIALIAS          ,
715     D3DRS_MULTISAMPLEMASK               ,
716     D3DRS_NORMALIZENORMALS              ,
717     D3DRS_PATCHEDGESTYLE                ,
718     D3DRS_PATCHSEGMENTS                 ,
719     D3DRS_POINTSCALE_A                  ,
720     D3DRS_POINTSCALE_B                  ,
721     D3DRS_POINTSCALE_C                  ,
722     D3DRS_POINTSCALEENABLE              ,
723     D3DRS_POINTSIZE                     ,
724     D3DRS_POINTSIZE_MAX                 ,
725     D3DRS_POINTSIZE_MIN                 ,
726     D3DRS_POINTSPRITEENABLE             ,
727     D3DRS_RANGEFOGENABLE                ,
728     D3DRS_SOFTWAREVERTEXPROCESSING      ,
729     D3DRS_SPECULARMATERIALSOURCE        ,
730     D3DRS_TWEENFACTOR                   ,
731     D3DRS_VERTEXBLEND
732 };
733
734 DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
735     D3DTSS_TEXCOORDINDEX         ,
736     D3DTSS_TEXTURETRANSFORMFLAGS
737 };