2 * state block implementation
4 * Copyright 2002 Raphael Junqueira
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.
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.
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
30 #include "wine/debug.h"
32 #include "d3d8_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
36 /* Used for CreateStateBlock */
37 #define NUM_SAVEDPIXELSTATES_R 38
38 #define NUM_SAVEDPIXELSTATES_T 27
39 #define NUM_SAVEDVERTEXSTATES_R 33
40 #define NUM_SAVEDVERTEXSTATES_T 2
45 extern DWORD SavedPixelStates_R
[NUM_SAVEDPIXELSTATES_R
];
46 extern DWORD SavedPixelStates_T
[NUM_SAVEDPIXELSTATES_T
];
47 extern DWORD SavedVertexStates_R
[NUM_SAVEDVERTEXSTATES_R
];
48 extern DWORD SavedVertexStates_T
[NUM_SAVEDVERTEXSTATES_T
];
49 static const float idmatrix
[16] = {
56 HRESULT WINAPI
IDirect3DDeviceImpl_InitStartupStateBlock(IDirect3DDevice8Impl
* This
) {
60 LPDIRECT3DDEVICE8 iface
= (LPDIRECT3DDEVICE8
) This
;
62 /* Note this may have a large overhead but it should only be executed
63 once, in order to initialize the complete state of the device and
64 all opengl equivalents */
65 TRACE("-----------------------> Setting up device defaults...\n");
66 This
->StateBlock
->blockType
= D3DSBT_ALL
;
68 /* FIXME: Set some of the defaults for lights, transforms etc */
69 memcpy(&This
->StateBlock
->transforms
[D3DTS_PROJECTION
], &idmatrix
, sizeof(idmatrix
));
70 memcpy(&This
->StateBlock
->transforms
[D3DTS_VIEW
], &idmatrix
, sizeof(idmatrix
));
71 for (i
= 0; i
< 256; ++i
) {
72 memcpy(&This
->StateBlock
->transforms
[D3DTS_WORLDMATRIX(i
)], &idmatrix
, sizeof(idmatrix
));
76 if (This
->PresentParms
.EnableAutoDepthStencil
) {
77 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZENABLE
, D3DZB_TRUE
);
79 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZENABLE
, D3DZB_FALSE
);
81 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FILLMODE
, D3DFILL_SOLID
);
82 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SHADEMODE
, D3DSHADE_GOURAUD
);
83 lp
.wRepeatFactor
= 0; lp
.wLinePattern
= 0; IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_LINEPATTERN
, (DWORD
) &lp
);
84 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZWRITEENABLE
, TRUE
);
85 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ALPHATESTENABLE
, FALSE
);
86 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_LASTPIXEL
, TRUE
);
87 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SRCBLEND
, D3DBLEND_ONE
);
88 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_DESTBLEND
, D3DBLEND_ZERO
);
89 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_CULLMODE
, D3DCULL_CCW
);
90 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZFUNC
, D3DCMP_LESSEQUAL
);
91 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ALPHAFUNC
, D3DCMP_ALWAYS
);
92 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ALPHAREF
, 0xff); /*??*/
93 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_DITHERENABLE
, FALSE
);
94 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ALPHABLENDENABLE
, FALSE
);
95 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGENABLE
, FALSE
);
96 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SPECULARENABLE
, FALSE
);
97 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZVISIBLE
, 0);
98 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGCOLOR
, 0);
99 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGTABLEMODE
, D3DFOG_NONE
);
100 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGSTART
, 0.0f
);
101 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGEND
, 1.0f
);
102 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGDENSITY
, 1.0f
);
103 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_EDGEANTIALIAS
, FALSE
);
104 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZBIAS
, 0);
105 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_RANGEFOGENABLE
, FALSE
);
106 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILENABLE
, FALSE
);
107 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILFAIL
, D3DSTENCILOP_KEEP
);
108 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILZFAIL
, D3DSTENCILOP_KEEP
);
109 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILPASS
, D3DSTENCILOP_KEEP
);
111 /* Setting stencil func also uses values for stencil ref/mask, so manually set defaults
112 * so only a single call performed (and ensure defaults initialized before making that call)
114 * IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILREF, 0);
115 * IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILMASK, 0xFFFFFFFF);
117 This
->StateBlock
->renderstate
[D3DRS_STENCILREF
] = 0;
118 This
->StateBlock
->renderstate
[D3DRS_STENCILMASK
] = 0xFFFFFFFF;
119 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILFUNC
, D3DCMP_ALWAYS
);
120 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILWRITEMASK
, 0xFFFFFFFF);
121 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_TEXTUREFACTOR
, 0xFFFFFFFF);
122 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP0
, 0);
123 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP1
, 0);
124 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP2
, 0);
125 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP3
, 0);
126 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP4
, 0);
127 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP5
, 0);
128 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP6
, 0);
129 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP7
, 0);
130 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_CLIPPING
, TRUE
);
131 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_LIGHTING
, TRUE
);
132 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_AMBIENT
, 0);
133 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGVERTEXMODE
, D3DFOG_NONE
);
134 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_COLORVERTEX
, TRUE
);
135 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_LOCALVIEWER
, TRUE
);
136 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_NORMALIZENORMALS
, FALSE
);
137 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_DIFFUSEMATERIALSOURCE
, D3DMCS_COLOR1
);
138 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SPECULARMATERIALSOURCE
, D3DMCS_COLOR2
);
139 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_AMBIENTMATERIALSOURCE
, D3DMCS_COLOR2
);
140 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_EMISSIVEMATERIALSOURCE
, D3DMCS_MATERIAL
);
141 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_VERTEXBLEND
, D3DVBF_DISABLE
);
142 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_CLIPPLANEENABLE
, 0);
143 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SOFTWAREVERTEXPROCESSING
, FALSE
);
144 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSIZE
, 1.0f
);
145 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSIZE_MIN
, 0.0f
);
146 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSPRITEENABLE
, FALSE
);
147 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSCALEENABLE
, FALSE
);
148 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSCALE_A
, TRUE
);
149 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSCALE_B
, TRUE
);
150 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSCALE_C
, TRUE
);
151 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_MULTISAMPLEANTIALIAS
, TRUE
);
152 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_MULTISAMPLEMASK
, 0xFFFFFFFF);
153 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_PATCHEDGESTYLE
, D3DPATCHEDGE_DISCRETE
);
154 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_PATCHSEGMENTS
, 1.0f
);
155 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_DEBUGMONITORTOKEN
, D3DDMT_DISABLE
);
156 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSIZE_MAX
, (DWORD
) 64.0f
);
157 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_INDEXEDVERTEXBLENDENABLE
, FALSE
);
158 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_COLORWRITEENABLE
, 0x0000000F);
159 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_TWEENFACTOR
, (DWORD
) 0.0f
);
160 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_BLENDOP
, D3DBLENDOP_ADD
);
161 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POSITIONORDER
, D3DORDER_CUBIC
);
162 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_NORMALORDER
, D3DORDER_LINEAR
);
164 /* Texture Stage States - Put directly into state block, we will call function below */
165 for (i
= 0; i
< GL_LIMITS(textures
); i
++) {
166 memcpy(&This
->StateBlock
->transforms
[D3DTS_TEXTURE0
+ i
], &idmatrix
, sizeof(idmatrix
));
167 This
->StateBlock
->texture_state
[i
][D3DTSS_COLOROP
] = (i
==0)? D3DTOP_MODULATE
: D3DTOP_DISABLE
;
168 This
->StateBlock
->texture_state
[i
][D3DTSS_COLORARG1
] = D3DTA_TEXTURE
;
169 This
->StateBlock
->texture_state
[i
][D3DTSS_COLORARG2
] = D3DTA_CURRENT
;
170 This
->StateBlock
->texture_state
[i
][D3DTSS_ALPHAOP
] = (i
==0)? D3DTOP_SELECTARG1
: D3DTOP_DISABLE
;
171 This
->StateBlock
->texture_state
[i
][D3DTSS_ALPHAARG1
] = D3DTA_TEXTURE
;
172 This
->StateBlock
->texture_state
[i
][D3DTSS_ALPHAARG2
] = D3DTA_CURRENT
;
173 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVMAT00
] = (DWORD
) 0.0;
174 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVMAT01
] = (DWORD
) 0.0;
175 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVMAT10
] = (DWORD
) 0.0;
176 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVMAT11
] = (DWORD
) 0.0;
177 This
->StateBlock
->texture_state
[i
][D3DTSS_TEXCOORDINDEX
] = i
;
178 This
->StateBlock
->texture_state
[i
][D3DTSS_ADDRESSU
] = D3DTADDRESS_WRAP
;
179 This
->StateBlock
->texture_state
[i
][D3DTSS_ADDRESSV
] = D3DTADDRESS_WRAP
;
180 This
->StateBlock
->texture_state
[i
][D3DTSS_BORDERCOLOR
] = 0x00;
181 This
->StateBlock
->texture_state
[i
][D3DTSS_MAGFILTER
] = D3DTEXF_POINT
;
182 This
->StateBlock
->texture_state
[i
][D3DTSS_MINFILTER
] = D3DTEXF_POINT
;
183 This
->StateBlock
->texture_state
[i
][D3DTSS_MIPFILTER
] = D3DTEXF_NONE
;
184 This
->StateBlock
->texture_state
[i
][D3DTSS_MIPMAPLODBIAS
] = 0;
185 This
->StateBlock
->texture_state
[i
][D3DTSS_MAXMIPLEVEL
] = 0;
186 This
->StateBlock
->texture_state
[i
][D3DTSS_MAXANISOTROPY
] = 1;
187 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVLSCALE
] = (DWORD
) 0.0;
188 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVLOFFSET
] = (DWORD
) 0.0;
189 This
->StateBlock
->texture_state
[i
][D3DTSS_TEXTURETRANSFORMFLAGS
] = D3DTTFF_DISABLE
;
190 This
->StateBlock
->texture_state
[i
][D3DTSS_ADDRESSW
] = D3DTADDRESS_WRAP
;
191 This
->StateBlock
->texture_state
[i
][D3DTSS_COLORARG0
] = D3DTA_CURRENT
;
192 This
->StateBlock
->texture_state
[i
][D3DTSS_ALPHAARG0
] = D3DTA_CURRENT
;
193 This
->StateBlock
->texture_state
[i
][D3DTSS_RESULTARG
] = D3DTA_CURRENT
;
196 /* Under DirectX you can have texture stage operations even if no texture is
197 bound, whereas opengl will only do texture operations when a valid texture is
198 bound. We emulate this by creating dummy textures and binding them to each
199 texture stage, but disable all stages by default. Hence if a stage is enabled
200 then the default texture will kick in until replaced by a SetTexture call */
204 for (i
= 0; i
< GL_LIMITS(textures
); i
++) {
207 /* Note this avoids calling settexture, so pretend it has been called */
208 This
->StateBlock
->Set
.textures
[i
] = TRUE
;
209 This
->StateBlock
->Changed
.textures
[i
] = TRUE
;
210 This
->StateBlock
->textures
[i
] = NULL
;
212 /* Make appropriate texture active */
213 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
214 #if defined(GL_VERSION_1_3)
215 glActiveTexture(GL_TEXTURE0
+ i
);
217 glActiveTextureARB(GL_TEXTURE0_ARB
+ i
);
219 checkGLcall("glActiveTextureARB");
221 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
224 /* Generate an opengl texture name */
225 glGenTextures(1, &This
->dummyTextureName
[i
]);
226 checkGLcall("glGenTextures");
227 TRACE("Dummy Texture %d given name %d\n", i
, This
->dummyTextureName
[i
]);
229 /* Generate a dummy 1d texture */
230 This
->StateBlock
->textureDimensions
[i
] = GL_TEXTURE_1D
;
231 glBindTexture(GL_TEXTURE_1D
, This
->dummyTextureName
[i
]);
232 checkGLcall("glBindTexture");
234 glTexImage1D(GL_TEXTURE_1D
, 0, GL_LUMINANCE
, 1, 0, GL_LUMINANCE
, GL_UNSIGNED_BYTE
, &white
);
235 checkGLcall("glTexImage1D");
237 /* Reapply all the texture state information to this texture */
238 setupTextureStates(iface
, i
, REAPPLY_ALL
);
243 /* defaulting palettes */
244 for (i
= 0; i
< MAX_PALETTES
; ++i
) {
245 for (j
= 0; j
< 256; ++j
) {
246 This
->palettes
[i
][j
].peRed
= 0xFF;
247 This
->palettes
[i
][j
].peGreen
= 0xFF;
248 This
->palettes
[i
][j
].peBlue
= 0xFF;
249 This
->palettes
[i
][j
].peFlags
= 0xFF;
252 This
->currentPalette
= 0;
254 TRACE("-----------------------> Device defaults now set up...\n");
261 HRESULT WINAPI
IDirect3DDeviceImpl_CreateStateBlock(IDirect3DDevice8Impl
* This
, D3DSTATEBLOCKTYPE Type
, IDirect3DStateBlockImpl
** ppStateBlock
) {
262 IDirect3DStateBlockImpl
* object
;
265 TRACE("(%p) : Type(%d)\n", This
, Type
);
267 /* Allocate Storage */
268 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DStateBlockImpl
));
270 if (NULL
== This
->StateBlock
) { /** if it the main stateblock only do init and returns */
271 /*object->lpVtbl = &Direct3DStateBlock9_Vtbl;*/
272 object
->device
= This
;
274 object
->blockType
= Type
;
275 This
->StateBlock
= object
;
276 /* don't forget to init it calling InitStartupStateBlock */
279 memcpy(object
, This
->StateBlock
, sizeof(IDirect3DStateBlockImpl
));
281 *ppStateBlock
= (IDirect3DStateBlockImpl
*) 0xFFFFFFFF;
282 return E_OUTOFMEMORY
;
284 /*object->lpVtbl = &Direct3DStateBlock9_Vtbl;*/
285 object
->device
= This
;
287 object
->blockType
= Type
;
289 TRACE("Updating changed flags appropriate for type %d\n", Type
);
291 if (Type
== D3DSBT_ALL
) {
292 TRACE("ALL => Pretend everything has changed\n");
293 memset(&object
->Changed
, TRUE
, sizeof(This
->StateBlock
->Changed
));
295 } else if (Type
== D3DSBT_PIXELSTATE
) {
297 memset(&object
->Changed
, FALSE
, sizeof(This
->StateBlock
->Changed
));
299 /* TODO: Pixel Shader Constants */
300 object
->Changed
.pixelShader
= TRUE
;
301 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_R
; i
++) {
302 object
->Changed
.renderstate
[SavedPixelStates_R
[i
]] = TRUE
;
304 for (j
= 0; j
< GL_LIMITS(textures
); i
++) {
305 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_T
; i
++) {
306 object
->Changed
.texture_state
[j
][SavedPixelStates_T
[i
]] = TRUE
;
310 } else if (Type
== D3DSBT_VERTEXSTATE
) {
312 memset(&object
->Changed
, FALSE
, sizeof(This
->StateBlock
->Changed
));
314 /* TODO: Vertex Shader Constants */
315 object
->Changed
.vertexShader
= TRUE
;
316 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_R
; i
++) {
317 object
->Changed
.renderstate
[SavedVertexStates_R
[i
]] = TRUE
;
319 for (j
= 0; j
< GL_LIMITS(textures
); i
++) {
320 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_T
; i
++) {
321 object
->Changed
.texture_state
[j
][SavedVertexStates_T
[i
]] = TRUE
;
325 /* Duplicate light chain */
327 PLIGHTINFOEL
*src
= NULL
;
328 PLIGHTINFOEL
*dst
= NULL
;
329 PLIGHTINFOEL
*newEl
= NULL
;
331 src
= This
->StateBlock
->lights
;
332 object
->lights
= NULL
;
335 newEl
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PLIGHTINFOEL
));
336 if (newEl
== NULL
) return D3DERR_OUTOFVIDEOMEMORY
;
337 memcpy(newEl
, src
, sizeof(PLIGHTINFOEL
));
339 newEl
->changed
= TRUE
;
340 newEl
->enabledChanged
= TRUE
;
342 object
->lights
= newEl
;
352 FIXME("Unrecognized state block type %d\n", Type
);
354 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, object
);
356 *ppStateBlock
= object
;
360 /** yakkk temporary waiting for Release */
361 HRESULT WINAPI
IDirect3DDeviceImpl_DeleteStateBlock(IDirect3DDevice8Impl
* This
, IDirect3DStateBlockImpl
* pSB
) {
364 TRACE("(%p) : freeing StateBlock %p\n", This
, pSB
);
366 if (tmp
) tmp
= tmp
->next
;
367 while (tmp
!= NULL
) {
368 HeapFree(GetProcessHeap(), 0, (void *)(tmp
->prev
));
371 if (tmp
) HeapFree(GetProcessHeap(), 0, (void *)tmp
);
372 HeapFree(GetProcessHeap(), 0, (void *)pSB
);
376 HRESULT WINAPI
IDirect3DDeviceImpl_BeginStateBlock(IDirect3DDevice8Impl
* This
) {
377 IDirect3DStateBlockImpl
* object
;
379 TRACE("(%p)\n", This
);
381 if (This
->isRecordingState
) {
382 TRACE("(%p) already recording! returning error\n", This
);
383 return D3DERR_INVALIDCALL
;
386 /* Allocate Storage */
387 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DStateBlockImpl
));
390 return E_OUTOFMEMORY
;
392 /*object->lpVtbl = &Direct3DVextexShaderDeclaration8_Vtbl;*/
393 object
->device
= This
;
396 This
->isRecordingState
= TRUE
;
397 This
->UpdateStateBlock
= object
;
402 HRESULT WINAPI
IDirect3DDeviceImpl_EndStateBlock(IDirect3DDevice8Impl
* This
, IDirect3DStateBlockImpl
** ppStateBlock
) {
403 TRACE("(%p)\n", This
);
405 if (!This
->isRecordingState
) {
406 TRACE("(%p) not recording! returning error\n", This
);
407 *ppStateBlock
= NULL
;
408 return D3DERR_INVALIDCALL
;
411 This
->UpdateStateBlock
->blockType
= D3DSBT_RECORDED
;
412 *ppStateBlock
= This
->UpdateStateBlock
; /* FIXME: AddRef() */
413 This
->isRecordingState
= FALSE
;
414 This
->UpdateStateBlock
= This
->StateBlock
;
416 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, *ppStateBlock
);
420 HRESULT WINAPI
IDirect3DDeviceImpl_ApplyStateBlock(IDirect3DDevice8Impl
* This
, IDirect3DStateBlockImpl
* pSB
) {
423 LPDIRECT3DDEVICE8 iface
= (LPDIRECT3DDEVICE8
) This
;
425 TRACE("(%p) : Applying state block %p ------------------v\n", This
, pSB
);
427 /* FIXME: Only apply applicable states not all states */
429 if (pSB
->blockType
== D3DSBT_RECORDED
|| pSB
->blockType
== D3DSBT_ALL
|| pSB
->blockType
== D3DSBT_VERTEXSTATE
) {
431 PLIGHTINFOEL
*toDo
= pSB
->lights
;
432 while (toDo
!= NULL
) {
434 IDirect3DDevice8Impl_SetLight(iface
, toDo
->OriginalIndex
, &toDo
->OriginalParms
);
435 if (toDo
->enabledChanged
)
436 IDirect3DDevice8Impl_LightEnable(iface
, toDo
->OriginalIndex
, toDo
->lightEnabled
);
440 if (pSB
->Set
.vertexShader
&& pSB
->Changed
.vertexShader
)
441 IDirect3DDevice8Impl_SetVertexShader(iface
, pSB
->VertexShader
);
443 /* TODO: Vertex Shader Constants */
446 if (pSB
->blockType
== D3DSBT_RECORDED
|| pSB
->blockType
== D3DSBT_ALL
|| pSB
->blockType
== D3DSBT_PIXELSTATE
) {
448 if (pSB
->Set
.pixelShader
&& pSB
->Changed
.pixelShader
)
449 IDirect3DDevice8Impl_SetPixelShader(iface
, pSB
->PixelShader
);
451 /* TODO: Pixel Shader Constants */
454 /* Others + Render & Texture */
455 if (pSB
->blockType
== D3DSBT_RECORDED
|| pSB
->blockType
== D3DSBT_ALL
) {
456 for (i
= 0; i
< HIGHEST_TRANSFORMSTATE
; i
++) {
457 if (pSB
->Set
.transform
[i
] && pSB
->Changed
.transform
[i
])
458 IDirect3DDevice8Impl_SetTransform(iface
, i
, &pSB
->transforms
[i
]);
461 if (pSB
->Set
.Indices
&& pSB
->Changed
.Indices
)
462 IDirect3DDevice8Impl_SetIndices(iface
, pSB
->pIndexData
, pSB
->baseVertexIndex
);
464 if (pSB
->Set
.material
&& pSB
->Changed
.material
)
465 IDirect3DDevice8Impl_SetMaterial(iface
, &pSB
->material
);
467 if (pSB
->Set
.viewport
&& pSB
->Changed
.viewport
)
468 IDirect3DDevice8Impl_SetViewport(iface
, &pSB
->viewport
);
470 for (i
=0; i
<MAX_STREAMS
; i
++) {
471 if (pSB
->Set
.stream_source
[i
] && pSB
->Changed
.stream_source
[i
])
472 IDirect3DDevice8Impl_SetStreamSource(iface
, i
, pSB
->stream_source
[i
], pSB
->stream_stride
[i
]);
475 for (i
= 0; i
< GL_LIMITS(clipplanes
); i
++) {
476 if (pSB
->Set
.clipplane
[i
] && pSB
->Changed
.clipplane
[i
]) {
479 clip
[0] = pSB
->clipplane
[i
][0];
480 clip
[1] = pSB
->clipplane
[i
][1];
481 clip
[2] = pSB
->clipplane
[i
][2];
482 clip
[3] = pSB
->clipplane
[i
][3];
483 IDirect3DDevice8Impl_SetClipPlane(iface
, i
, clip
);
488 for (i
= 0; i
< HIGHEST_RENDER_STATE
; i
++) {
489 if (pSB
->Set
.renderstate
[i
] && pSB
->Changed
.renderstate
[i
])
490 IDirect3DDevice8Impl_SetRenderState(iface
, i
, pSB
->renderstate
[i
]);
494 for (j
= 0; j
< GL_LIMITS(textures
); j
++) {
495 for (i
= 0; i
< HIGHEST_TEXTURE_STATE
; i
++) {
496 if (pSB
->Set
.texture_state
[j
][i
] && pSB
->Changed
.texture_state
[j
][i
]) {
497 IDirect3DDevice8Impl_SetTextureStageState(iface
, j
, i
, pSB
->texture_state
[j
][i
]);
500 if (pSB
->Set
.textures
[j
] && pSB
->Changed
.textures
[j
]) {
501 IDirect3DDevice8Impl_SetTexture(iface
, j
, pSB
->textures
[j
]);
506 } else if (pSB
->blockType
== D3DSBT_PIXELSTATE
) {
508 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_R
; i
++) {
509 if (pSB
->Set
.renderstate
[SavedPixelStates_R
[i
]] && pSB
->Changed
.renderstate
[SavedPixelStates_R
[i
]])
510 IDirect3DDevice8Impl_SetRenderState(iface
, SavedPixelStates_R
[i
], pSB
->renderstate
[SavedPixelStates_R
[i
]]);
514 for (j
= 0; j
< GL_LIMITS(textures
); i
++) {
515 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_T
; i
++) {
516 if (pSB
->Set
.texture_state
[j
][SavedPixelStates_T
[i
]] &&
517 pSB
->Changed
.texture_state
[j
][SavedPixelStates_T
[i
]])
518 IDirect3DDevice8Impl_SetTextureStageState(iface
, j
, SavedPixelStates_T
[i
], pSB
->texture_state
[j
][SavedPixelStates_T
[i
]]);
522 } else if (pSB
->blockType
== D3DSBT_VERTEXSTATE
) {
524 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_R
; i
++) {
525 if (pSB
->Set
.renderstate
[SavedVertexStates_R
[i
]] && pSB
->Changed
.renderstate
[SavedVertexStates_R
[i
]])
526 IDirect3DDevice8Impl_SetRenderState(iface
, SavedVertexStates_R
[i
], pSB
->renderstate
[SavedVertexStates_R
[i
]]);
529 for (j
= 0; j
< GL_LIMITS(textures
); i
++) {
530 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_T
; i
++) {
531 if (pSB
->Set
.texture_state
[j
][SavedVertexStates_T
[i
]] &&
532 pSB
->Changed
.texture_state
[j
][SavedVertexStates_T
[i
]])
533 IDirect3DDevice8Impl_SetTextureStageState(iface
, j
, SavedVertexStates_T
[i
], pSB
->texture_state
[j
][SavedVertexStates_T
[i
]]);
539 FIXME("Unrecognized state block type %d\n", pSB
->blockType
);
541 memcpy(&This
->StateBlock
->Changed
, &pSB
->Changed
, sizeof(This
->StateBlock
->Changed
));
542 TRACE("(%p) : Applied state block %p ------------------^\n", This
, pSB
);
547 HRESULT WINAPI
IDirect3DDeviceImpl_CaptureStateBlock(IDirect3DDevice8Impl
* This
, IDirect3DStateBlockImpl
* updateBlock
) {
548 LPDIRECT3DDEVICE8 iface
= (LPDIRECT3DDEVICE8
) This
;
551 TRACE("(%p) : Updating state block %p ------------------v \n", This
, updateBlock
);
553 /* If not recorded, then update can just recapture */
554 if (updateBlock
->blockType
!= D3DSBT_RECORDED
) {
555 IDirect3DStateBlockImpl
* tmpBlock
;
556 IDirect3DDeviceImpl_CreateStateBlock(This
, updateBlock
->blockType
, &tmpBlock
);
558 /* Note just swap the light chains over so when deleting, the old one goes */
559 tmp
= updateBlock
->lights
;
560 memcpy(updateBlock
, tmpBlock
, sizeof(IDirect3DStateBlockImpl
));
561 tmpBlock
->lights
= tmp
;
563 /* Delete the temporary one (which points to the old light chain though */
564 IDirect3DDeviceImpl_DeleteStateBlock(This
, tmpBlock
);
570 /* Recorded => Only update 'changed' values */
571 if (updateBlock
->Set
.vertexShader
&& updateBlock
->VertexShader
!= This
->StateBlock
->VertexShader
) {
572 updateBlock
->VertexShader
= This
->StateBlock
->VertexShader
;
573 TRACE("Updating vertex shader to %ld\n", This
->StateBlock
->VertexShader
);
576 /* TODO: Vertex Shader Constants */
578 /* Lights... For a recorded state block, we just had a chain of actions to perform,
579 so we need to walk that chain and update any actions which differ */
580 src
= updateBlock
->lights
;
581 while (src
!= NULL
) {
582 PLIGHTINFOEL
*realLight
= NULL
;
584 /* Locate the light in the live lights */
585 realLight
= This
->StateBlock
->lights
;
586 while (realLight
!= NULL
&& realLight
->OriginalIndex
!= src
->OriginalIndex
) realLight
= realLight
->next
;
588 if (realLight
== NULL
) {
589 FIXME("A captured light no longer exists...?\n");
592 /* If 'changed' then its a SetLight command. Rather than comparing to see
593 if the OriginalParms have changed and then copy them (twice through
594 memory) just do the copy */
596 TRACE("Updating lights for light %ld\n", src
->OriginalIndex
);
597 memcpy(&src
->OriginalParms
, &realLight
->OriginalParms
, sizeof(PLIGHTINFOEL
));
600 /* If 'enabledChanged' then its a LightEnable command */
601 if (src
->enabledChanged
) {
602 TRACE("Updating lightEnabled for light %ld\n", src
->OriginalIndex
);
603 src
->lightEnabled
= realLight
->lightEnabled
;
612 if (updateBlock
->Set
.pixelShader
&& updateBlock
->PixelShader
!= This
->StateBlock
->PixelShader
) {
613 TRACE("Updating pixel shader to %ld\n", This
->StateBlock
->PixelShader
);
614 IDirect3DDevice8Impl_SetVertexShader(iface
, updateBlock
->PixelShader
);
617 /* TODO: Pixel Shader Constants */
619 /* Others + Render & Texture */
620 for (i
= 0; i
< HIGHEST_TRANSFORMSTATE
; i
++) {
621 if (updateBlock
->Set
.transform
[i
] && memcmp(&This
->StateBlock
->transforms
[i
],
622 &updateBlock
->transforms
[i
],
623 sizeof(D3DMATRIX
)) != 0) {
624 TRACE("Updating transform %d\n", i
);
625 memcpy(&updateBlock
->transforms
[i
], &This
->StateBlock
->transforms
[i
], sizeof(D3DMATRIX
));
629 if (updateBlock
->Set
.Indices
&& ((updateBlock
->pIndexData
!= This
->StateBlock
->pIndexData
)
630 || (updateBlock
->baseVertexIndex
!= This
->StateBlock
->baseVertexIndex
))) {
631 TRACE("Updating pindexData to %p, baseVertexIndex to %d\n",
632 This
->StateBlock
->pIndexData
, This
->StateBlock
->baseVertexIndex
);
633 updateBlock
->pIndexData
= This
->StateBlock
->pIndexData
;
634 updateBlock
->baseVertexIndex
= This
->StateBlock
->baseVertexIndex
;
637 if (updateBlock
->Set
.material
&& memcmp(&This
->StateBlock
->material
,
638 &updateBlock
->material
,
639 sizeof(D3DMATERIAL8
)) != 0) {
640 TRACE("Updating material\n");
641 memcpy(&updateBlock
->material
, &This
->StateBlock
->material
, sizeof(D3DMATERIAL8
));
644 if (updateBlock
->Set
.viewport
&& memcmp(&This
->StateBlock
->viewport
,
645 &updateBlock
->viewport
,
646 sizeof(D3DVIEWPORT8
)) != 0) {
647 TRACE("Updating viewport\n");
648 memcpy(&updateBlock
->viewport
, &This
->StateBlock
->viewport
, sizeof(D3DVIEWPORT8
));
651 for (i
= 0; i
< MAX_STREAMS
; i
++) {
652 if (updateBlock
->Set
.stream_source
[i
] &&
653 ((updateBlock
->stream_stride
[i
] != This
->StateBlock
->stream_stride
[i
]) ||
654 (updateBlock
->stream_source
[i
] != This
->StateBlock
->stream_source
[i
]))) {
655 TRACE("Updating stream source %d to %p, stride to %d\n", i
, This
->StateBlock
->stream_source
[i
],
656 This
->StateBlock
->stream_stride
[i
]);
657 updateBlock
->stream_stride
[i
] = This
->StateBlock
->stream_stride
[i
];
658 updateBlock
->stream_source
[i
] = This
->StateBlock
->stream_source
[i
];
662 for (i
= 0; i
< GL_LIMITS(clipplanes
); i
++) {
663 if (updateBlock
->Set
.clipplane
[i
] && memcmp(&This
->StateBlock
->clipplane
[i
],
664 &updateBlock
->clipplane
[i
],
665 sizeof(updateBlock
->clipplane
)) != 0) {
667 TRACE("Updating clipplane %d\n", i
);
668 memcpy(&updateBlock
->clipplane
[i
], &This
->StateBlock
->clipplane
[i
],
669 sizeof(updateBlock
->clipplane
));
674 for (i
= 0; i
< HIGHEST_RENDER_STATE
; i
++) {
676 if (updateBlock
->Set
.renderstate
[i
] && (updateBlock
->renderstate
[i
] !=
677 This
->StateBlock
->renderstate
[i
])) {
678 TRACE("Updating renderstate %d to %ld\n", i
, This
->StateBlock
->renderstate
[i
]);
679 updateBlock
->renderstate
[i
] = This
->StateBlock
->renderstate
[i
];
684 for (j
= 0; j
< GL_LIMITS(textures
); j
++) {
685 for (i
= 0; i
< HIGHEST_TEXTURE_STATE
; i
++) {
687 if (updateBlock
->Set
.texture_state
[j
][i
] && (updateBlock
->texture_state
[j
][i
] !=
688 This
->StateBlock
->texture_state
[j
][i
])) {
689 TRACE("Updating texturestagestate %d,%d to %ld (was %ld)\n", j
,i
, This
->StateBlock
->texture_state
[j
][i
],
690 updateBlock
->texture_state
[j
][i
]);
691 updateBlock
->texture_state
[j
][i
] = This
->StateBlock
->texture_state
[j
][i
];
694 if (updateBlock
->Set
.textures
[j
] && (updateBlock
->textures
[j
] != This
->StateBlock
->textures
[j
])) {
695 TRACE("Updating texture %d to %p (was %p)\n", j
, This
->StateBlock
->textures
[j
], updateBlock
->textures
[j
]);
696 updateBlock
->textures
[j
] = This
->StateBlock
->textures
[j
];
703 TRACE("(%p) : Updated state block %p ------------------^\n", This
, updateBlock
);
708 DWORD SavedPixelStates_R
[NUM_SAVEDPIXELSTATES_R
] = {
709 D3DRS_ALPHABLENDENABLE
,
712 D3DRS_ALPHATESTENABLE
,
714 D3DRS_COLORWRITEENABLE
,
717 D3DRS_EDGEANTIALIAS
,
726 D3DRS_STENCILENABLE
,
732 D3DRS_STENCILWRITEMASK
,
734 D3DRS_TEXTUREFACTOR
,
749 DWORD SavedPixelStates_T
[NUM_SAVEDPIXELSTATES_T
] = {
758 D3DTSS_BUMPENVLOFFSET
,
759 D3DTSS_BUMPENVLSCALE
,
760 D3DTSS_BUMPENVMAT00
,
761 D3DTSS_BUMPENVMAT01
,
762 D3DTSS_BUMPENVMAT10
,
763 D3DTSS_BUMPENVMAT11
,
769 D3DTSS_MAXANISOTROPY
,
773 D3DTSS_MIPMAPLODBIAS
,
775 D3DTSS_TEXCOORDINDEX
,
776 D3DTSS_TEXTURETRANSFORMFLAGS
779 DWORD SavedVertexStates_R
[NUM_SAVEDVERTEXSTATES_R
] = {
781 D3DRS_AMBIENTMATERIALSOURCE
,
783 D3DRS_CLIPPLANEENABLE
,
785 D3DRS_DIFFUSEMATERIALSOURCE
,
786 D3DRS_EMISSIVEMATERIALSOURCE
,
791 D3DRS_FOGVERTEXMODE
,
792 D3DRS_INDEXEDVERTEXBLENDENABLE
,
795 D3DRS_MULTISAMPLEANTIALIAS
,
796 D3DRS_MULTISAMPLEMASK
,
797 D3DRS_NORMALIZENORMALS
,
798 D3DRS_PATCHEDGESTYLE
,
799 D3DRS_PATCHSEGMENTS
,
803 D3DRS_POINTSCALEENABLE
,
805 D3DRS_POINTSIZE_MAX
,
806 D3DRS_POINTSIZE_MIN
,
807 D3DRS_POINTSPRITEENABLE
,
808 D3DRS_RANGEFOGENABLE
,
809 D3DRS_SOFTWAREVERTEXPROCESSING
,
810 D3DRS_SPECULARMATERIALSOURCE
,
815 DWORD SavedVertexStates_T
[NUM_SAVEDVERTEXSTATES_T
] = {
816 D3DTSS_TEXCOORDINDEX
,
817 D3DTSS_TEXTURETRANSFORMFLAGS