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
) {
67 LPDIRECT3DDEVICE8 iface
= (LPDIRECT3DDEVICE8
) This
;
69 /* Note this may have a large overhead but it should only be executed
70 once, in order to initialize the complete state of the device and
71 all opengl equivalents */
72 TRACE("-----------------------> Setting up device defaults...\n");
73 This
->StateBlock
->blockType
= D3DSBT_ALL
;
75 /* FIXME: Set some of the defaults for lights, transforms etc */
76 memcpy(&This
->StateBlock
->transforms
[D3DTS_PROJECTION
], &idmatrix
, sizeof(idmatrix
));
77 memcpy(&This
->StateBlock
->transforms
[D3DTS_VIEW
], &idmatrix
, sizeof(idmatrix
));
78 for (i
= 0; i
< 256; ++i
) {
79 memcpy(&This
->StateBlock
->transforms
[D3DTS_WORLDMATRIX(i
)], &idmatrix
, sizeof(idmatrix
));
83 if (This
->PresentParms
.EnableAutoDepthStencil
) {
84 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZENABLE
, D3DZB_TRUE
);
86 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZENABLE
, D3DZB_FALSE
);
88 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FILLMODE
, D3DFILL_SOLID
);
89 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SHADEMODE
, D3DSHADE_GOURAUD
);
91 lp
.lp
.wRepeatFactor
= 0; lp
.lp
.wLinePattern
= 0;
92 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_LINEPATTERN
, lp
.d
);
93 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZWRITEENABLE
, TRUE
);
94 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ALPHATESTENABLE
, FALSE
);
95 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_LASTPIXEL
, TRUE
);
96 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SRCBLEND
, D3DBLEND_ONE
);
97 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_DESTBLEND
, D3DBLEND_ZERO
);
98 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_CULLMODE
, D3DCULL_CCW
);
99 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZFUNC
, D3DCMP_LESSEQUAL
);
100 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ALPHAFUNC
, D3DCMP_ALWAYS
);
101 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ALPHAREF
, 0xff); /*??*/
102 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_DITHERENABLE
, FALSE
);
103 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ALPHABLENDENABLE
, FALSE
);
104 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGENABLE
, FALSE
);
105 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SPECULARENABLE
, FALSE
);
106 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZVISIBLE
, 0);
107 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGCOLOR
, 0);
108 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGTABLEMODE
, D3DFOG_NONE
);
110 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGSTART
, tmpfloat
.d
);
112 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGEND
, tmpfloat
.d
);
114 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGDENSITY
, tmpfloat
.d
);
115 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_EDGEANTIALIAS
, FALSE
);
116 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZBIAS
, 0);
117 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_RANGEFOGENABLE
, FALSE
);
118 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILENABLE
, FALSE
);
119 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILFAIL
, D3DSTENCILOP_KEEP
);
120 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILZFAIL
, D3DSTENCILOP_KEEP
);
121 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILPASS
, D3DSTENCILOP_KEEP
);
123 /* Setting stencil func also uses values for stencil ref/mask, so manually set defaults
124 * so only a single call performed (and ensure defaults initialized before making that call)
126 * IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILREF, 0);
127 * IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILMASK, 0xFFFFFFFF);
129 This
->StateBlock
->renderstate
[D3DRS_STENCILREF
] = 0;
130 This
->StateBlock
->renderstate
[D3DRS_STENCILMASK
] = 0xFFFFFFFF;
131 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILFUNC
, D3DCMP_ALWAYS
);
132 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILWRITEMASK
, 0xFFFFFFFF);
133 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_TEXTUREFACTOR
, 0xFFFFFFFF);
134 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP0
, 0);
135 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP1
, 0);
136 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP2
, 0);
137 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP3
, 0);
138 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP4
, 0);
139 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP5
, 0);
140 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP6
, 0);
141 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP7
, 0);
142 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_CLIPPING
, TRUE
);
143 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_LIGHTING
, TRUE
);
144 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_AMBIENT
, 0);
145 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGVERTEXMODE
, D3DFOG_NONE
);
146 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_COLORVERTEX
, TRUE
);
147 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_LOCALVIEWER
, TRUE
);
148 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_NORMALIZENORMALS
, FALSE
);
149 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_DIFFUSEMATERIALSOURCE
, D3DMCS_COLOR1
);
150 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SPECULARMATERIALSOURCE
, D3DMCS_COLOR2
);
151 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_AMBIENTMATERIALSOURCE
, D3DMCS_COLOR2
);
152 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_EMISSIVEMATERIALSOURCE
, D3DMCS_MATERIAL
);
153 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_VERTEXBLEND
, D3DVBF_DISABLE
);
154 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_CLIPPLANEENABLE
, 0);
155 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SOFTWAREVERTEXPROCESSING
, FALSE
);
157 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSIZE
, tmpfloat
.d
);
159 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSIZE_MIN
, tmpfloat
.d
);
160 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSPRITEENABLE
, FALSE
);
161 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSCALEENABLE
, FALSE
);
162 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSCALE_A
, TRUE
);
163 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSCALE_B
, TRUE
);
164 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSCALE_C
, TRUE
);
165 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_MULTISAMPLEANTIALIAS
, TRUE
);
166 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_MULTISAMPLEMASK
, 0xFFFFFFFF);
167 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_PATCHEDGESTYLE
, D3DPATCHEDGE_DISCRETE
);
169 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_PATCHSEGMENTS
, tmpfloat
.d
);
170 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_DEBUGMONITORTOKEN
, D3DDMT_DISABLE
);
172 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSIZE_MAX
, tmpfloat
.d
);
173 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_INDEXEDVERTEXBLENDENABLE
, FALSE
);
174 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_COLORWRITEENABLE
, 0x0000000F);
176 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_TWEENFACTOR
, tmpfloat
.d
);
177 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_BLENDOP
, D3DBLENDOP_ADD
);
178 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POSITIONORDER
, D3DORDER_CUBIC
);
179 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_NORMALORDER
, D3DORDER_LINEAR
);
181 /** clipping status */
182 This
->StateBlock
->clip_status
.ClipUnion
= 0;
183 This
->StateBlock
->clip_status
.ClipIntersection
= 0xFFFFFFFF;
185 /* Texture Stage States - Put directly into state block, we will call function below */
186 for (i
= 0; i
< GL_LIMITS(textures
); i
++) {
187 memcpy(&This
->StateBlock
->transforms
[D3DTS_TEXTURE0
+ i
], &idmatrix
, sizeof(idmatrix
));
188 This
->StateBlock
->texture_state
[i
][D3DTSS_COLOROP
] = (i
==0)? D3DTOP_MODULATE
: D3DTOP_DISABLE
;
189 This
->StateBlock
->texture_state
[i
][D3DTSS_COLORARG1
] = D3DTA_TEXTURE
;
190 This
->StateBlock
->texture_state
[i
][D3DTSS_COLORARG2
] = D3DTA_CURRENT
;
191 This
->StateBlock
->texture_state
[i
][D3DTSS_ALPHAOP
] = (i
==0)? D3DTOP_SELECTARG1
: D3DTOP_DISABLE
;
192 This
->StateBlock
->texture_state
[i
][D3DTSS_ALPHAARG1
] = D3DTA_TEXTURE
;
193 This
->StateBlock
->texture_state
[i
][D3DTSS_ALPHAARG2
] = D3DTA_CURRENT
;
194 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVMAT00
] = (DWORD
) 0.0;
195 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVMAT01
] = (DWORD
) 0.0;
196 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVMAT10
] = (DWORD
) 0.0;
197 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVMAT11
] = (DWORD
) 0.0;
198 This
->StateBlock
->texture_state
[i
][D3DTSS_TEXCOORDINDEX
] = i
;
199 This
->StateBlock
->texture_state
[i
][D3DTSS_ADDRESSU
] = D3DTADDRESS_WRAP
;
200 This
->StateBlock
->texture_state
[i
][D3DTSS_ADDRESSV
] = D3DTADDRESS_WRAP
;
201 This
->StateBlock
->texture_state
[i
][D3DTSS_BORDERCOLOR
] = 0x00;
202 This
->StateBlock
->texture_state
[i
][D3DTSS_MAGFILTER
] = D3DTEXF_POINT
;
203 This
->StateBlock
->texture_state
[i
][D3DTSS_MINFILTER
] = D3DTEXF_POINT
;
204 This
->StateBlock
->texture_state
[i
][D3DTSS_MIPFILTER
] = D3DTEXF_NONE
;
205 This
->StateBlock
->texture_state
[i
][D3DTSS_MIPMAPLODBIAS
] = 0;
206 This
->StateBlock
->texture_state
[i
][D3DTSS_MAXMIPLEVEL
] = 0;
207 This
->StateBlock
->texture_state
[i
][D3DTSS_MAXANISOTROPY
] = 1;
208 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVLSCALE
] = (DWORD
) 0.0;
209 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVLOFFSET
] = (DWORD
) 0.0;
210 This
->StateBlock
->texture_state
[i
][D3DTSS_TEXTURETRANSFORMFLAGS
] = D3DTTFF_DISABLE
;
211 This
->StateBlock
->texture_state
[i
][D3DTSS_ADDRESSW
] = D3DTADDRESS_WRAP
;
212 This
->StateBlock
->texture_state
[i
][D3DTSS_COLORARG0
] = D3DTA_CURRENT
;
213 This
->StateBlock
->texture_state
[i
][D3DTSS_ALPHAARG0
] = D3DTA_CURRENT
;
214 This
->StateBlock
->texture_state
[i
][D3DTSS_RESULTARG
] = D3DTA_CURRENT
;
217 /* Under DirectX you can have texture stage operations even if no texture is
218 bound, whereas opengl will only do texture operations when a valid texture is
219 bound. We emulate this by creating dummy textures and binding them to each
220 texture stage, but disable all stages by default. Hence if a stage is enabled
221 then the default texture will kick in until replaced by a SetTexture call */
225 for (i
= 0; i
< GL_LIMITS(textures
); i
++) {
228 /* Note this avoids calling settexture, so pretend it has been called */
229 This
->StateBlock
->Set
.textures
[i
] = TRUE
;
230 This
->StateBlock
->Changed
.textures
[i
] = TRUE
;
231 This
->StateBlock
->textures
[i
] = NULL
;
233 /* Make appropriate texture active */
234 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
235 #if defined(GL_VERSION_1_3)
236 glActiveTexture(GL_TEXTURE0
+ i
);
238 glActiveTextureARB(GL_TEXTURE0_ARB
+ i
);
240 checkGLcall("glActiveTextureARB");
242 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
245 /* Generate an opengl texture name */
246 glGenTextures(1, &This
->dummyTextureName
[i
]);
247 checkGLcall("glGenTextures");
248 TRACE("Dummy Texture %d given name %d\n", i
, This
->dummyTextureName
[i
]);
250 /* Generate a dummy 1d texture */
251 This
->StateBlock
->textureDimensions
[i
] = GL_TEXTURE_1D
;
252 glBindTexture(GL_TEXTURE_1D
, This
->dummyTextureName
[i
]);
253 checkGLcall("glBindTexture");
255 glTexImage1D(GL_TEXTURE_1D
, 0, GL_LUMINANCE
, 1, 0, GL_LUMINANCE
, GL_UNSIGNED_BYTE
, &white
);
256 checkGLcall("glTexImage1D");
258 /* Reapply all the texture state information to this texture */
259 setupTextureStates(iface
, i
, REAPPLY_ALL
);
264 /* defaulting palettes */
265 for (i
= 0; i
< MAX_PALETTES
; ++i
) {
266 for (j
= 0; j
< 256; ++j
) {
267 This
->palettes
[i
][j
].peRed
= 0xFF;
268 This
->palettes
[i
][j
].peGreen
= 0xFF;
269 This
->palettes
[i
][j
].peBlue
= 0xFF;
270 This
->palettes
[i
][j
].peFlags
= 0xFF;
273 This
->currentPalette
= 0;
275 TRACE("-----------------------> Device defaults now set up...\n");
282 HRESULT WINAPI
IDirect3DDeviceImpl_CreateStateBlock(IDirect3DDevice8Impl
* This
, D3DSTATEBLOCKTYPE Type
, IDirect3DStateBlockImpl
** ppStateBlock
) {
283 IDirect3DStateBlockImpl
* object
;
286 TRACE("(%p) : Type(%d)\n", This
, Type
);
288 /* Allocate Storage */
289 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DStateBlockImpl
));
291 if (NULL
== This
->StateBlock
) { /** if it the main stateblock only do init and returns */
292 /*object->lpVtbl = &Direct3DStateBlock9_Vtbl;*/
293 object
->device
= This
;
295 object
->blockType
= Type
;
296 This
->StateBlock
= object
;
297 /* don't forget to init it calling InitStartupStateBlock */
300 memcpy(object
, This
->StateBlock
, sizeof(IDirect3DStateBlockImpl
));
302 *ppStateBlock
= (IDirect3DStateBlockImpl
*) 0xFFFFFFFF;
303 return E_OUTOFMEMORY
;
305 /*object->lpVtbl = &Direct3DStateBlock9_Vtbl;*/
306 object
->device
= This
;
308 object
->blockType
= Type
;
310 TRACE("Updating changed flags appropriate for type %d\n", Type
);
312 if (Type
== D3DSBT_ALL
) {
313 TRACE("ALL => Pretend everything has changed\n");
314 memset(&object
->Changed
, TRUE
, sizeof(This
->StateBlock
->Changed
));
316 } else if (Type
== D3DSBT_PIXELSTATE
) {
318 memset(&object
->Changed
, FALSE
, sizeof(This
->StateBlock
->Changed
));
320 /* TODO: Pixel Shader Constants */
321 object
->Changed
.pixelShader
= TRUE
;
322 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_R
; i
++) {
323 object
->Changed
.renderstate
[SavedPixelStates_R
[i
]] = TRUE
;
325 for (j
= 0; j
< GL_LIMITS(textures
); i
++) {
326 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_T
; i
++) {
327 object
->Changed
.texture_state
[j
][SavedPixelStates_T
[i
]] = TRUE
;
331 } else if (Type
== D3DSBT_VERTEXSTATE
) {
333 memset(&object
->Changed
, FALSE
, sizeof(This
->StateBlock
->Changed
));
335 /* TODO: Vertex Shader Constants */
336 object
->Changed
.vertexShader
= TRUE
;
337 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_R
; i
++) {
338 object
->Changed
.renderstate
[SavedVertexStates_R
[i
]] = TRUE
;
340 for (j
= 0; j
< GL_LIMITS(textures
); i
++) {
341 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_T
; i
++) {
342 object
->Changed
.texture_state
[j
][SavedVertexStates_T
[i
]] = TRUE
;
346 /* Duplicate light chain */
348 PLIGHTINFOEL
*src
= NULL
;
349 PLIGHTINFOEL
*dst
= NULL
;
350 PLIGHTINFOEL
*newEl
= NULL
;
352 src
= This
->StateBlock
->lights
;
353 object
->lights
= NULL
;
356 newEl
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PLIGHTINFOEL
));
357 if (newEl
== NULL
) return D3DERR_OUTOFVIDEOMEMORY
;
358 memcpy(newEl
, src
, sizeof(PLIGHTINFOEL
));
360 newEl
->changed
= TRUE
;
361 newEl
->enabledChanged
= TRUE
;
363 object
->lights
= newEl
;
373 FIXME("Unrecognized state block type %d\n", Type
);
375 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, object
);
377 *ppStateBlock
= object
;
381 /** yakkk temporary waiting for Release */
382 HRESULT WINAPI
IDirect3DDeviceImpl_DeleteStateBlock(IDirect3DDevice8Impl
* This
, IDirect3DStateBlockImpl
* pSB
) {
385 TRACE("(%p) : freeing StateBlock %p\n", This
, pSB
);
387 if (tmp
) tmp
= tmp
->next
;
388 while (tmp
!= NULL
) {
389 HeapFree(GetProcessHeap(), 0, (void *)(tmp
->prev
));
392 HeapFree(GetProcessHeap(), 0, (void *)tmp
);
393 HeapFree(GetProcessHeap(), 0, (void *)pSB
);
397 HRESULT WINAPI
IDirect3DDeviceImpl_BeginStateBlock(IDirect3DDevice8Impl
* This
) {
398 IDirect3DStateBlockImpl
* object
;
400 TRACE("(%p)\n", This
);
402 if (This
->isRecordingState
) {
403 TRACE("(%p) already recording! returning error\n", This
);
404 return D3DERR_INVALIDCALL
;
407 /* Allocate Storage */
408 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DStateBlockImpl
));
411 return E_OUTOFMEMORY
;
413 /*object->lpVtbl = &Direct3DVextexShaderDeclaration8_Vtbl;*/
414 object
->device
= This
;
417 This
->isRecordingState
= TRUE
;
418 This
->UpdateStateBlock
= object
;
423 HRESULT WINAPI
IDirect3DDeviceImpl_EndStateBlock(IDirect3DDevice8Impl
* This
, IDirect3DStateBlockImpl
** ppStateBlock
) {
424 TRACE("(%p)\n", This
);
426 if (!This
->isRecordingState
) {
427 TRACE("(%p) not recording! returning error\n", This
);
428 *ppStateBlock
= NULL
;
429 return D3DERR_INVALIDCALL
;
432 This
->UpdateStateBlock
->blockType
= D3DSBT_RECORDED
;
433 *ppStateBlock
= This
->UpdateStateBlock
; /* FIXME: AddRef() */
434 This
->isRecordingState
= FALSE
;
435 This
->UpdateStateBlock
= This
->StateBlock
;
437 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, *ppStateBlock
);
441 HRESULT WINAPI
IDirect3DDeviceImpl_ApplyStateBlock(IDirect3DDevice8Impl
* This
, IDirect3DStateBlockImpl
* pSB
) {
444 LPDIRECT3DDEVICE8 iface
= (LPDIRECT3DDEVICE8
) This
;
446 TRACE("(%p) : Applying state block %p ------------------v\n", This
, pSB
);
448 /* FIXME: Only apply applicable states not all states */
450 if (pSB
->blockType
== D3DSBT_RECORDED
|| pSB
->blockType
== D3DSBT_ALL
|| pSB
->blockType
== D3DSBT_VERTEXSTATE
) {
452 PLIGHTINFOEL
*toDo
= pSB
->lights
;
453 while (toDo
!= NULL
) {
455 IDirect3DDevice8Impl_SetLight(iface
, toDo
->OriginalIndex
, &toDo
->OriginalParms
);
456 if (toDo
->enabledChanged
)
457 IDirect3DDevice8Impl_LightEnable(iface
, toDo
->OriginalIndex
, toDo
->lightEnabled
);
461 if (pSB
->Set
.vertexShader
&& pSB
->Changed
.vertexShader
)
462 IDirect3DDevice8Impl_SetVertexShader(iface
, pSB
->VertexShader
);
464 /* TODO: Vertex Shader Constants */
467 if (pSB
->blockType
== D3DSBT_RECORDED
|| pSB
->blockType
== D3DSBT_ALL
|| pSB
->blockType
== D3DSBT_PIXELSTATE
) {
469 if (pSB
->Set
.pixelShader
&& pSB
->Changed
.pixelShader
)
470 IDirect3DDevice8Impl_SetPixelShader(iface
, pSB
->PixelShader
);
472 /* TODO: Pixel Shader Constants */
475 /* Others + Render & Texture */
476 if (pSB
->blockType
== D3DSBT_RECORDED
|| pSB
->blockType
== D3DSBT_ALL
) {
477 for (i
= 0; i
< HIGHEST_TRANSFORMSTATE
; i
++) {
478 if (pSB
->Set
.transform
[i
] && pSB
->Changed
.transform
[i
])
479 IDirect3DDevice8Impl_SetTransform(iface
, i
, &pSB
->transforms
[i
]);
482 if (pSB
->Set
.Indices
&& pSB
->Changed
.Indices
)
483 IDirect3DDevice8Impl_SetIndices(iface
, pSB
->pIndexData
, pSB
->baseVertexIndex
);
485 if (pSB
->Set
.material
&& pSB
->Changed
.material
)
486 IDirect3DDevice8Impl_SetMaterial(iface
, &pSB
->material
);
488 if (pSB
->Set
.viewport
&& pSB
->Changed
.viewport
)
489 IDirect3DDevice8Impl_SetViewport(iface
, &pSB
->viewport
);
491 for (i
=0; i
<MAX_STREAMS
; i
++) {
492 if (pSB
->Set
.stream_source
[i
] && pSB
->Changed
.stream_source
[i
])
493 IDirect3DDevice8Impl_SetStreamSource(iface
, i
, pSB
->stream_source
[i
], pSB
->stream_stride
[i
]);
496 for (i
= 0; i
< GL_LIMITS(clipplanes
); i
++) {
497 if (pSB
->Set
.clipplane
[i
] && pSB
->Changed
.clipplane
[i
]) {
500 clip
[0] = pSB
->clipplane
[i
][0];
501 clip
[1] = pSB
->clipplane
[i
][1];
502 clip
[2] = pSB
->clipplane
[i
][2];
503 clip
[3] = pSB
->clipplane
[i
][3];
504 IDirect3DDevice8Impl_SetClipPlane(iface
, i
, clip
);
509 for (i
= 0; i
< HIGHEST_RENDER_STATE
; i
++) {
510 if (pSB
->Set
.renderstate
[i
] && pSB
->Changed
.renderstate
[i
])
511 IDirect3DDevice8Impl_SetRenderState(iface
, i
, pSB
->renderstate
[i
]);
515 for (j
= 0; j
< GL_LIMITS(textures
); j
++) {
516 for (i
= 0; i
< HIGHEST_TEXTURE_STATE
; i
++) {
517 if (pSB
->Set
.texture_state
[j
][i
] && pSB
->Changed
.texture_state
[j
][i
]) {
518 IDirect3DDevice8Impl_SetTextureStageState(iface
, j
, i
, pSB
->texture_state
[j
][i
]);
521 if (pSB
->Set
.textures
[j
] && pSB
->Changed
.textures
[j
]) {
522 IDirect3DDevice8Impl_SetTexture(iface
, j
, pSB
->textures
[j
]);
527 } else if (pSB
->blockType
== D3DSBT_PIXELSTATE
) {
529 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_R
; i
++) {
530 if (pSB
->Set
.renderstate
[SavedPixelStates_R
[i
]] && pSB
->Changed
.renderstate
[SavedPixelStates_R
[i
]])
531 IDirect3DDevice8Impl_SetRenderState(iface
, SavedPixelStates_R
[i
], pSB
->renderstate
[SavedPixelStates_R
[i
]]);
535 for (j
= 0; j
< GL_LIMITS(textures
); i
++) {
536 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_T
; i
++) {
537 if (pSB
->Set
.texture_state
[j
][SavedPixelStates_T
[i
]] &&
538 pSB
->Changed
.texture_state
[j
][SavedPixelStates_T
[i
]])
539 IDirect3DDevice8Impl_SetTextureStageState(iface
, j
, SavedPixelStates_T
[i
], pSB
->texture_state
[j
][SavedPixelStates_T
[i
]]);
543 } else if (pSB
->blockType
== D3DSBT_VERTEXSTATE
) {
545 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_R
; i
++) {
546 if (pSB
->Set
.renderstate
[SavedVertexStates_R
[i
]] && pSB
->Changed
.renderstate
[SavedVertexStates_R
[i
]])
547 IDirect3DDevice8Impl_SetRenderState(iface
, SavedVertexStates_R
[i
], pSB
->renderstate
[SavedVertexStates_R
[i
]]);
550 for (j
= 0; j
< GL_LIMITS(textures
); i
++) {
551 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_T
; i
++) {
552 if (pSB
->Set
.texture_state
[j
][SavedVertexStates_T
[i
]] &&
553 pSB
->Changed
.texture_state
[j
][SavedVertexStates_T
[i
]])
554 IDirect3DDevice8Impl_SetTextureStageState(iface
, j
, SavedVertexStates_T
[i
], pSB
->texture_state
[j
][SavedVertexStates_T
[i
]]);
560 FIXME("Unrecognized state block type %d\n", pSB
->blockType
);
562 memcpy(&This
->StateBlock
->Changed
, &pSB
->Changed
, sizeof(This
->StateBlock
->Changed
));
563 TRACE("(%p) : Applied state block %p ------------------^\n", This
, pSB
);
568 HRESULT WINAPI
IDirect3DDeviceImpl_CaptureStateBlock(IDirect3DDevice8Impl
* This
, IDirect3DStateBlockImpl
* updateBlock
) {
569 LPDIRECT3DDEVICE8 iface
= (LPDIRECT3DDEVICE8
) This
;
572 TRACE("(%p) : Updating state block %p ------------------v \n", This
, updateBlock
);
574 /* If not recorded, then update can just recapture */
575 if (updateBlock
->blockType
!= D3DSBT_RECORDED
) {
576 IDirect3DStateBlockImpl
* tmpBlock
;
577 IDirect3DDeviceImpl_CreateStateBlock(This
, updateBlock
->blockType
, &tmpBlock
);
579 /* Note just swap the light chains over so when deleting, the old one goes */
580 tmp
= updateBlock
->lights
;
581 memcpy(updateBlock
, tmpBlock
, sizeof(IDirect3DStateBlockImpl
));
582 tmpBlock
->lights
= tmp
;
584 /* Delete the temporary one (which points to the old light chain though */
585 IDirect3DDeviceImpl_DeleteStateBlock(This
, tmpBlock
);
591 /* Recorded => Only update 'changed' values */
592 if (updateBlock
->Set
.vertexShader
&& updateBlock
->VertexShader
!= This
->StateBlock
->VertexShader
) {
593 updateBlock
->VertexShader
= This
->StateBlock
->VertexShader
;
594 TRACE("Updating vertex shader to %ld\n", This
->StateBlock
->VertexShader
);
597 /* TODO: Vertex Shader Constants */
599 /* Lights... For a recorded state block, we just had a chain of actions to perform,
600 so we need to walk that chain and update any actions which differ */
601 src
= updateBlock
->lights
;
602 while (src
!= NULL
) {
603 PLIGHTINFOEL
*realLight
= NULL
;
605 /* Locate the light in the live lights */
606 realLight
= This
->StateBlock
->lights
;
607 while (realLight
!= NULL
&& realLight
->OriginalIndex
!= src
->OriginalIndex
) realLight
= realLight
->next
;
609 if (realLight
== NULL
) {
610 FIXME("A captured light no longer exists...?\n");
613 /* If 'changed' then its a SetLight command. Rather than comparing to see
614 if the OriginalParms have changed and then copy them (twice through
615 memory) just do the copy */
617 TRACE("Updating lights for light %ld\n", src
->OriginalIndex
);
618 memcpy(&src
->OriginalParms
, &realLight
->OriginalParms
, sizeof(PLIGHTINFOEL
));
621 /* If 'enabledChanged' then its a LightEnable command */
622 if (src
->enabledChanged
) {
623 TRACE("Updating lightEnabled for light %ld\n", src
->OriginalIndex
);
624 src
->lightEnabled
= realLight
->lightEnabled
;
633 if (updateBlock
->Set
.pixelShader
&& updateBlock
->PixelShader
!= This
->StateBlock
->PixelShader
) {
634 TRACE("Updating pixel shader to %ld\n", This
->StateBlock
->PixelShader
);
635 IDirect3DDevice8Impl_SetVertexShader(iface
, updateBlock
->PixelShader
);
638 /* TODO: Pixel Shader Constants */
640 /* Others + Render & Texture */
641 for (i
= 0; i
< HIGHEST_TRANSFORMSTATE
; i
++) {
642 if (updateBlock
->Set
.transform
[i
] && memcmp(&This
->StateBlock
->transforms
[i
],
643 &updateBlock
->transforms
[i
],
644 sizeof(D3DMATRIX
)) != 0) {
645 TRACE("Updating transform %d\n", i
);
646 memcpy(&updateBlock
->transforms
[i
], &This
->StateBlock
->transforms
[i
], sizeof(D3DMATRIX
));
650 if (updateBlock
->Set
.Indices
&& ((updateBlock
->pIndexData
!= This
->StateBlock
->pIndexData
)
651 || (updateBlock
->baseVertexIndex
!= This
->StateBlock
->baseVertexIndex
))) {
652 TRACE("Updating pindexData to %p, baseVertexIndex to %d\n",
653 This
->StateBlock
->pIndexData
, This
->StateBlock
->baseVertexIndex
);
654 updateBlock
->pIndexData
= This
->StateBlock
->pIndexData
;
655 updateBlock
->baseVertexIndex
= This
->StateBlock
->baseVertexIndex
;
658 if (updateBlock
->Set
.material
&& memcmp(&This
->StateBlock
->material
,
659 &updateBlock
->material
,
660 sizeof(D3DMATERIAL8
)) != 0) {
661 TRACE("Updating material\n");
662 memcpy(&updateBlock
->material
, &This
->StateBlock
->material
, sizeof(D3DMATERIAL8
));
665 if (updateBlock
->Set
.viewport
&& memcmp(&This
->StateBlock
->viewport
,
666 &updateBlock
->viewport
,
667 sizeof(D3DVIEWPORT8
)) != 0) {
668 TRACE("Updating viewport\n");
669 memcpy(&updateBlock
->viewport
, &This
->StateBlock
->viewport
, sizeof(D3DVIEWPORT8
));
672 for (i
= 0; i
< MAX_STREAMS
; i
++) {
673 if (updateBlock
->Set
.stream_source
[i
] &&
674 ((updateBlock
->stream_stride
[i
] != This
->StateBlock
->stream_stride
[i
]) ||
675 (updateBlock
->stream_source
[i
] != This
->StateBlock
->stream_source
[i
]))) {
676 TRACE("Updating stream source %d to %p, stride to %d\n", i
, This
->StateBlock
->stream_source
[i
],
677 This
->StateBlock
->stream_stride
[i
]);
678 updateBlock
->stream_stride
[i
] = This
->StateBlock
->stream_stride
[i
];
679 updateBlock
->stream_source
[i
] = This
->StateBlock
->stream_source
[i
];
683 for (i
= 0; i
< GL_LIMITS(clipplanes
); i
++) {
684 if (updateBlock
->Set
.clipplane
[i
] && memcmp(&This
->StateBlock
->clipplane
[i
],
685 &updateBlock
->clipplane
[i
],
686 sizeof(updateBlock
->clipplane
)) != 0) {
688 TRACE("Updating clipplane %d\n", i
);
689 memcpy(&updateBlock
->clipplane
[i
], &This
->StateBlock
->clipplane
[i
],
690 sizeof(updateBlock
->clipplane
));
695 for (i
= 0; i
< HIGHEST_RENDER_STATE
; i
++) {
697 if (updateBlock
->Set
.renderstate
[i
] && (updateBlock
->renderstate
[i
] !=
698 This
->StateBlock
->renderstate
[i
])) {
699 TRACE("Updating renderstate %d to %ld\n", i
, This
->StateBlock
->renderstate
[i
]);
700 updateBlock
->renderstate
[i
] = This
->StateBlock
->renderstate
[i
];
705 for (j
= 0; j
< GL_LIMITS(textures
); j
++) {
706 for (i
= 0; i
< HIGHEST_TEXTURE_STATE
; i
++) {
708 if (updateBlock
->Set
.texture_state
[j
][i
] && (updateBlock
->texture_state
[j
][i
] !=
709 This
->StateBlock
->texture_state
[j
][i
])) {
710 TRACE("Updating texturestagestate %d,%d to %ld (was %ld)\n", j
,i
, This
->StateBlock
->texture_state
[j
][i
],
711 updateBlock
->texture_state
[j
][i
]);
712 updateBlock
->texture_state
[j
][i
] = This
->StateBlock
->texture_state
[j
][i
];
715 if (updateBlock
->Set
.textures
[j
] && (updateBlock
->textures
[j
] != This
->StateBlock
->textures
[j
])) {
716 TRACE("Updating texture %d to %p (was %p)\n", j
, This
->StateBlock
->textures
[j
], updateBlock
->textures
[j
]);
717 updateBlock
->textures
[j
] = This
->StateBlock
->textures
[j
];
724 TRACE("(%p) : Updated state block %p ------------------^\n", This
, updateBlock
);
729 DWORD SavedPixelStates_R
[NUM_SAVEDPIXELSTATES_R
] = {
730 D3DRS_ALPHABLENDENABLE
,
733 D3DRS_ALPHATESTENABLE
,
735 D3DRS_COLORWRITEENABLE
,
738 D3DRS_EDGEANTIALIAS
,
747 D3DRS_STENCILENABLE
,
753 D3DRS_STENCILWRITEMASK
,
755 D3DRS_TEXTUREFACTOR
,
770 DWORD SavedPixelStates_T
[NUM_SAVEDPIXELSTATES_T
] = {
779 D3DTSS_BUMPENVLOFFSET
,
780 D3DTSS_BUMPENVLSCALE
,
781 D3DTSS_BUMPENVMAT00
,
782 D3DTSS_BUMPENVMAT01
,
783 D3DTSS_BUMPENVMAT10
,
784 D3DTSS_BUMPENVMAT11
,
790 D3DTSS_MAXANISOTROPY
,
794 D3DTSS_MIPMAPLODBIAS
,
796 D3DTSS_TEXCOORDINDEX
,
797 D3DTSS_TEXTURETRANSFORMFLAGS
800 DWORD SavedVertexStates_R
[NUM_SAVEDVERTEXSTATES_R
] = {
802 D3DRS_AMBIENTMATERIALSOURCE
,
804 D3DRS_CLIPPLANEENABLE
,
806 D3DRS_DIFFUSEMATERIALSOURCE
,
807 D3DRS_EMISSIVEMATERIALSOURCE
,
812 D3DRS_FOGVERTEXMODE
,
813 D3DRS_INDEXEDVERTEXBLENDENABLE
,
816 D3DRS_MULTISAMPLEANTIALIAS
,
817 D3DRS_MULTISAMPLEMASK
,
818 D3DRS_NORMALIZENORMALS
,
819 D3DRS_PATCHEDGESTYLE
,
820 D3DRS_PATCHSEGMENTS
,
824 D3DRS_POINTSCALEENABLE
,
826 D3DRS_POINTSIZE_MAX
,
827 D3DRS_POINTSIZE_MIN
,
828 D3DRS_POINTSPRITEENABLE
,
829 D3DRS_RANGEFOGENABLE
,
830 D3DRS_SOFTWAREVERTEXPROCESSING
,
831 D3DRS_SPECULARMATERIALSOURCE
,
836 DWORD SavedVertexStates_T
[NUM_SAVEDVERTEXSTATES_T
] = {
837 D3DTSS_TEXCOORDINDEX
,
838 D3DTSS_TEXTURETRANSFORMFLAGS