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
27 #include "wine/debug.h"
31 #include "d3d8_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
35 /* Used for CreateStateBlock */
36 #define NUM_SAVEDPIXELSTATES_R 38
37 #define NUM_SAVEDPIXELSTATES_T 27
38 #define NUM_SAVEDVERTEXSTATES_R 33
39 #define NUM_SAVEDVERTEXSTATES_T 2
44 extern DWORD SavedPixelStates_R
[NUM_SAVEDPIXELSTATES_R
];
45 extern DWORD SavedPixelStates_T
[NUM_SAVEDPIXELSTATES_T
];
46 extern DWORD SavedVertexStates_R
[NUM_SAVEDVERTEXSTATES_R
];
47 extern DWORD SavedVertexStates_T
[NUM_SAVEDVERTEXSTATES_T
];
48 static const float idmatrix
[16] = {
55 HRESULT WINAPI
IDirect3DDeviceImpl_InitStartupStateBlock(IDirect3DDevice8Impl
* This
) {
59 LPDIRECT3DDEVICE8 iface
= (LPDIRECT3DDEVICE8
) This
;
61 /* Note this may have a large overhead but it should only be executed
62 once, in order to initialize the complete state of the device and
63 all opengl equivalents */
64 TRACE("-----------------------> Setting up device defaults...\n");
65 This
->StateBlock
->blockType
= D3DSBT_ALL
;
67 /* FIXME: Set some of the defaults for lights, transforms etc */
68 memcpy(&This
->StateBlock
->transforms
[D3DTS_PROJECTION
], &idmatrix
, sizeof(idmatrix
));
69 memcpy(&This
->StateBlock
->transforms
[D3DTS_VIEW
], &idmatrix
, sizeof(idmatrix
));
70 for (i
= 0; i
< 256; ++i
) {
71 memcpy(&This
->StateBlock
->transforms
[D3DTS_WORLDMATRIX(i
)], &idmatrix
, sizeof(idmatrix
));
75 if (This
->PresentParms
.EnableAutoDepthStencil
) {
76 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZENABLE
, D3DZB_TRUE
);
78 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZENABLE
, D3DZB_FALSE
);
80 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FILLMODE
, D3DFILL_SOLID
);
81 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SHADEMODE
, D3DSHADE_GOURAUD
);
82 lp
.wRepeatFactor
= 0; lp
.wLinePattern
= 0; IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_LINEPATTERN
, (DWORD
) &lp
);
83 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZWRITEENABLE
, TRUE
);
84 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ALPHATESTENABLE
, FALSE
);
85 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_LASTPIXEL
, TRUE
);
86 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SRCBLEND
, D3DBLEND_ONE
);
87 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_DESTBLEND
, D3DBLEND_ZERO
);
88 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_CULLMODE
, D3DCULL_CCW
);
89 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZFUNC
, D3DCMP_LESSEQUAL
);
90 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ALPHAFUNC
, D3DCMP_ALWAYS
);
91 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ALPHAREF
, 0xff); /*??*/
92 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_DITHERENABLE
, FALSE
);
93 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ALPHABLENDENABLE
, FALSE
);
94 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGENABLE
, FALSE
);
95 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SPECULARENABLE
, FALSE
);
96 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZVISIBLE
, 0);
97 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGCOLOR
, 0);
98 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGTABLEMODE
, D3DFOG_NONE
);
99 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGSTART
, 0.0f
);
100 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGEND
, 1.0f
);
101 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGDENSITY
, 1.0f
);
102 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_EDGEANTIALIAS
, FALSE
);
103 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZBIAS
, 0);
104 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_RANGEFOGENABLE
, FALSE
);
105 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILENABLE
, FALSE
);
106 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILFAIL
, D3DSTENCILOP_KEEP
);
107 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILZFAIL
, D3DSTENCILOP_KEEP
);
108 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILPASS
, D3DSTENCILOP_KEEP
);
110 /* Setting stencil func also uses values for stencil ref/mask, so manually set defaults
111 * so only a single call performed (and ensure defaults initialized before making that call)
113 * IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILREF, 0);
114 * IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILMASK, 0xFFFFFFFF);
116 This
->StateBlock
->renderstate
[D3DRS_STENCILREF
] = 0;
117 This
->StateBlock
->renderstate
[D3DRS_STENCILMASK
] = 0xFFFFFFFF;
118 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILFUNC
, D3DCMP_ALWAYS
);
119 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILWRITEMASK
, 0xFFFFFFFF);
120 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_TEXTUREFACTOR
, 0xFFFFFFFF);
121 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP0
, 0);
122 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP1
, 0);
123 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP2
, 0);
124 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP3
, 0);
125 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP4
, 0);
126 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP5
, 0);
127 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP6
, 0);
128 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP7
, 0);
129 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_CLIPPING
, TRUE
);
130 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_LIGHTING
, TRUE
);
131 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_AMBIENT
, 0);
132 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGVERTEXMODE
, D3DFOG_NONE
);
133 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_COLORVERTEX
, TRUE
);
134 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_LOCALVIEWER
, TRUE
);
135 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_NORMALIZENORMALS
, FALSE
);
136 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_DIFFUSEMATERIALSOURCE
, D3DMCS_COLOR1
);
137 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SPECULARMATERIALSOURCE
, D3DMCS_COLOR2
);
138 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_AMBIENTMATERIALSOURCE
, D3DMCS_COLOR2
);
139 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_EMISSIVEMATERIALSOURCE
, D3DMCS_MATERIAL
);
140 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_VERTEXBLEND
, D3DVBF_DISABLE
);
141 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_CLIPPLANEENABLE
, 0);
142 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SOFTWAREVERTEXPROCESSING
, FALSE
);
143 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSIZE
, 1.0f
);
144 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSIZE_MIN
, 0.0f
);
145 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSPRITEENABLE
, FALSE
);
146 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSCALEENABLE
, FALSE
);
147 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSCALE_A
, TRUE
);
148 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSCALE_B
, TRUE
);
149 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSCALE_C
, TRUE
);
150 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_MULTISAMPLEANTIALIAS
, TRUE
);
151 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_MULTISAMPLEMASK
, 0xFFFFFFFF);
152 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_PATCHEDGESTYLE
, D3DPATCHEDGE_DISCRETE
);
153 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_PATCHSEGMENTS
, 1.0f
);
154 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_DEBUGMONITORTOKEN
, D3DDMT_DISABLE
);
155 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSIZE_MAX
, (DWORD
) 64.0f
);
156 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_INDEXEDVERTEXBLENDENABLE
, FALSE
);
157 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_COLORWRITEENABLE
, 0x0000000F);
158 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_TWEENFACTOR
, (DWORD
) 0.0f
);
159 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_BLENDOP
, D3DBLENDOP_ADD
);
160 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POSITIONORDER
, D3DORDER_CUBIC
);
161 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_NORMALORDER
, D3DORDER_LINEAR
);
163 /* Texture Stage States - Put directly into state block, we will call function below */
164 for (i
= 0; i
< GL_LIMITS(textures
); i
++) {
165 memcpy(&This
->StateBlock
->transforms
[D3DTS_TEXTURE0
+ i
], &idmatrix
, sizeof(idmatrix
));
166 This
->StateBlock
->texture_state
[i
][D3DTSS_COLOROP
] = (i
==0)? D3DTOP_MODULATE
: D3DTOP_DISABLE
;
167 This
->StateBlock
->texture_state
[i
][D3DTSS_COLORARG1
] = D3DTA_TEXTURE
;
168 This
->StateBlock
->texture_state
[i
][D3DTSS_COLORARG2
] = D3DTA_CURRENT
;
169 This
->StateBlock
->texture_state
[i
][D3DTSS_ALPHAOP
] = (i
==0)? D3DTOP_SELECTARG1
: D3DTOP_DISABLE
;
170 This
->StateBlock
->texture_state
[i
][D3DTSS_ALPHAARG1
] = D3DTA_TEXTURE
;
171 This
->StateBlock
->texture_state
[i
][D3DTSS_ALPHAARG2
] = D3DTA_CURRENT
;
172 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVMAT00
] = (DWORD
) 0.0;
173 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVMAT01
] = (DWORD
) 0.0;
174 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVMAT10
] = (DWORD
) 0.0;
175 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVMAT11
] = (DWORD
) 0.0;
176 This
->StateBlock
->texture_state
[i
][D3DTSS_TEXCOORDINDEX
] = i
;
177 This
->StateBlock
->texture_state
[i
][D3DTSS_ADDRESSU
] = D3DTADDRESS_WRAP
;
178 This
->StateBlock
->texture_state
[i
][D3DTSS_ADDRESSV
] = D3DTADDRESS_WRAP
;
179 This
->StateBlock
->texture_state
[i
][D3DTSS_BORDERCOLOR
] = 0x00;
180 This
->StateBlock
->texture_state
[i
][D3DTSS_MAGFILTER
] = D3DTEXF_POINT
;
181 This
->StateBlock
->texture_state
[i
][D3DTSS_MINFILTER
] = D3DTEXF_POINT
;
182 This
->StateBlock
->texture_state
[i
][D3DTSS_MIPFILTER
] = D3DTEXF_NONE
;
183 This
->StateBlock
->texture_state
[i
][D3DTSS_MIPMAPLODBIAS
] = 0;
184 This
->StateBlock
->texture_state
[i
][D3DTSS_MAXMIPLEVEL
] = 0;
185 This
->StateBlock
->texture_state
[i
][D3DTSS_MAXANISOTROPY
] = 1;
186 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVLSCALE
] = (DWORD
) 0.0;
187 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVLOFFSET
] = (DWORD
) 0.0;
188 This
->StateBlock
->texture_state
[i
][D3DTSS_TEXTURETRANSFORMFLAGS
] = D3DTTFF_DISABLE
;
189 This
->StateBlock
->texture_state
[i
][D3DTSS_ADDRESSW
] = D3DTADDRESS_WRAP
;
190 This
->StateBlock
->texture_state
[i
][D3DTSS_COLORARG0
] = D3DTA_CURRENT
;
191 This
->StateBlock
->texture_state
[i
][D3DTSS_ALPHAARG0
] = D3DTA_CURRENT
;
192 This
->StateBlock
->texture_state
[i
][D3DTSS_RESULTARG
] = D3DTA_CURRENT
;
195 /* Under DirectX you can have texture stage operations even if no texture is
196 bound, whereas opengl will only do texture operations when a valid texture is
197 bound. We emulate this by creating dummy textures and binding them to each
198 texture stage, but disable all stages by default. Hence if a stage is enabled
199 then the default texture will kick in until replaced by a SetTexture call */
203 for (i
= 0; i
< GL_LIMITS(textures
); i
++) {
206 /* Note this avoids calling settexture, so pretend it has been called */
207 This
->StateBlock
->Set
.textures
[i
] = TRUE
;
208 This
->StateBlock
->Changed
.textures
[i
] = TRUE
;
209 This
->StateBlock
->textures
[i
] = NULL
;
211 /* Make appropriate texture active */
212 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
213 #if defined(GL_VERSION_1_3)
214 glActiveTexture(GL_TEXTURE0
+ i
);
216 glActiveTextureARB(GL_TEXTURE0_ARB
+ i
);
218 checkGLcall("glActiveTextureARB");
220 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
223 /* Generate an opengl texture name */
224 glGenTextures(1, &This
->dummyTextureName
[i
]);
225 checkGLcall("glGenTextures");
226 TRACE("Dummy Texture %d given name %d\n", i
, This
->dummyTextureName
[i
]);
228 /* Generate a dummy 1d texture */
229 This
->StateBlock
->textureDimensions
[i
] = GL_TEXTURE_1D
;
230 glBindTexture(GL_TEXTURE_1D
, This
->dummyTextureName
[i
]);
231 checkGLcall("glBindTexture");
233 glTexImage1D(GL_TEXTURE_1D
, 0, GL_LUMINANCE
, 1, 0, GL_LUMINANCE
, GL_UNSIGNED_BYTE
, &white
);
234 checkGLcall("glTexImage1D");
236 /* Reapply all the texture state information to this texture */
237 setupTextureStates(iface
, i
);
242 /* defaulting palettes */
243 for (i
= 0; i
< MAX_PALETTES
; ++i
) {
244 for (j
= 0; j
< 256; ++j
) {
245 This
->palettes
[i
][j
].peRed
= 0xFF;
246 This
->palettes
[i
][j
].peGreen
= 0xFF;
247 This
->palettes
[i
][j
].peBlue
= 0xFF;
248 This
->palettes
[i
][j
].peFlags
= 0xFF;
251 This
->currentPalette
= 0;
253 TRACE("-----------------------> Device defaults now set up...\n");
260 HRESULT WINAPI
IDirect3DDeviceImpl_CreateStateBlock(IDirect3DDevice8Impl
* This
, D3DSTATEBLOCKTYPE Type
, IDirect3DStateBlockImpl
** ppStateBlock
) {
261 IDirect3DStateBlockImpl
* object
;
264 TRACE("(%p) : Type(%d)\n", This
, Type
);
266 /* Allocate Storage */
267 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DStateBlockImpl
));
269 if (NULL
== This
->StateBlock
) { /** if it the main stateblock only do init and returns */
270 /*object->lpVtbl = &Direct3DStateBlock9_Vtbl;*/
271 object
->device
= This
;
273 object
->blockType
= Type
;
274 This
->StateBlock
= object
;
275 /* don't forget to init it calling InitStartupStateBlock */
278 memcpy(object
, This
->StateBlock
, sizeof(IDirect3DStateBlockImpl
));
280 *ppStateBlock
= (IDirect3DStateBlockImpl
*) 0xFFFFFFFF;
281 return E_OUTOFMEMORY
;
283 /*object->lpVtbl = &Direct3DStateBlock9_Vtbl;*/
284 object
->device
= This
;
286 object
->blockType
= Type
;
288 TRACE("Updating changed flags appropriate for type %d\n", Type
);
290 if (Type
== D3DSBT_ALL
) {
291 TRACE("ALL => Pretend everything has changed\n");
292 memset(&object
->Changed
, TRUE
, sizeof(This
->StateBlock
->Changed
));
294 } else if (Type
== D3DSBT_PIXELSTATE
) {
296 memset(&object
->Changed
, FALSE
, sizeof(This
->StateBlock
->Changed
));
298 /* TODO: Pixel Shader Constants */
299 object
->Changed
.pixelShader
= TRUE
;
300 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_R
; i
++) {
301 object
->Changed
.renderstate
[SavedPixelStates_R
[i
]] = TRUE
;
303 for (j
= 0; j
< GL_LIMITS(textures
); i
++) {
304 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_T
; i
++) {
305 object
->Changed
.texture_state
[j
][SavedPixelStates_T
[i
]] = TRUE
;
309 } else if (Type
== D3DSBT_VERTEXSTATE
) {
311 memset(&object
->Changed
, FALSE
, sizeof(This
->StateBlock
->Changed
));
313 /* TODO: Vertex Shader Constants */
314 object
->Changed
.vertexShader
= TRUE
;
315 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_R
; i
++) {
316 object
->Changed
.renderstate
[SavedVertexStates_R
[i
]] = TRUE
;
318 for (j
= 0; j
< GL_LIMITS(textures
); i
++) {
319 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_T
; i
++) {
320 object
->Changed
.texture_state
[j
][SavedVertexStates_T
[i
]] = TRUE
;
323 for (i
= 0; i
< GL_LIMITS(lights
); i
++) {
324 object
->Changed
.lightEnable
[i
] = TRUE
;
325 object
->Changed
.lights
[i
] = TRUE
;
329 FIXME("Unrecognized state block type %d\n", Type
);
331 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, object
);
333 *ppStateBlock
= object
;
337 /** yakkk temporary waiting for Release */
338 HRESULT WINAPI
IDirect3DDeviceImpl_DeleteStateBlock(IDirect3DDevice8Impl
* This
, IDirect3DStateBlockImpl
* pSB
) {
339 TRACE("(%p) : freeing StateBlock %p\n", This
, pSB
);
340 HeapFree(GetProcessHeap(), 0, (void *)pSB
);
344 HRESULT WINAPI
IDirect3DDeviceImpl_BeginStateBlock(IDirect3DDevice8Impl
* This
) {
345 IDirect3DStateBlockImpl
* object
;
347 TRACE("(%p)\n", This
);
349 if (This
->isRecordingState
) {
350 TRACE("(%p) already recording! returning error\n", This
);
351 return D3DERR_INVALIDCALL
;
354 /* Allocate Storage */
355 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DStateBlockImpl
));
358 return E_OUTOFMEMORY
;
360 /*object->lpVtbl = &Direct3DVextexShaderDeclaration8_Vtbl;*/
361 object
->device
= This
;
364 This
->isRecordingState
= TRUE
;
365 This
->UpdateStateBlock
= object
;
370 HRESULT WINAPI
IDirect3DDeviceImpl_EndStateBlock(IDirect3DDevice8Impl
* This
, IDirect3DStateBlockImpl
** ppStateBlock
) {
371 TRACE("(%p)\n", This
);
373 if (!This
->isRecordingState
) {
374 TRACE("(%p) not recording! returning error\n", This
);
375 *ppStateBlock
= NULL
;
376 return D3DERR_INVALIDCALL
;
379 This
->UpdateStateBlock
->blockType
= D3DSBT_RECORDED
;
380 *ppStateBlock
= This
->UpdateStateBlock
; /* FIXME: AddRef() */
381 This
->isRecordingState
= FALSE
;
382 This
->UpdateStateBlock
= This
->StateBlock
;
384 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, *ppStateBlock
);
388 HRESULT WINAPI
IDirect3DDeviceImpl_ApplyStateBlock(IDirect3DDevice8Impl
* This
, IDirect3DStateBlockImpl
* pSB
) {
391 LPDIRECT3DDEVICE8 iface
= (LPDIRECT3DDEVICE8
) This
;
393 TRACE("(%p) : Applying state block %p ------------------v\n", This
, pSB
);
395 /* FIXME: Only apply applicable states not all states */
397 if (pSB
->blockType
== D3DSBT_RECORDED
|| pSB
->blockType
== D3DSBT_ALL
|| pSB
->blockType
== D3DSBT_VERTEXSTATE
) {
399 for (i
= 0; i
< GL_LIMITS(lights
); i
++) {
401 if (pSB
->Set
.lightEnable
[i
] && pSB
->Changed
.lightEnable
[i
])
402 IDirect3DDevice8Impl_LightEnable(iface
, i
, pSB
->lightEnable
[i
]);
403 if (pSB
->Set
.lights
[i
] && pSB
->Changed
.lights
[i
])
404 IDirect3DDevice8Impl_SetLight(iface
, i
, &pSB
->lights
[i
]);
407 if (pSB
->Set
.vertexShader
&& pSB
->Changed
.vertexShader
)
408 IDirect3DDevice8Impl_SetVertexShader(iface
, pSB
->VertexShader
);
410 /* TODO: Vertex Shader Constants */
413 if (pSB
->blockType
== D3DSBT_RECORDED
|| pSB
->blockType
== D3DSBT_ALL
|| pSB
->blockType
== D3DSBT_PIXELSTATE
) {
415 if (pSB
->Set
.pixelShader
&& pSB
->Changed
.pixelShader
)
416 IDirect3DDevice8Impl_SetPixelShader(iface
, pSB
->PixelShader
);
418 /* TODO: Pixel Shader Constants */
421 /* Others + Render & Texture */
422 if (pSB
->blockType
== D3DSBT_RECORDED
|| pSB
->blockType
== D3DSBT_ALL
) {
423 for (i
= 0; i
< HIGHEST_TRANSFORMSTATE
; i
++) {
424 if (pSB
->Set
.transform
[i
] && pSB
->Changed
.transform
[i
])
425 IDirect3DDevice8Impl_SetTransform(iface
, i
, &pSB
->transforms
[i
]);
428 if (pSB
->Set
.Indices
&& pSB
->Changed
.Indices
)
429 IDirect3DDevice8Impl_SetIndices(iface
, pSB
->pIndexData
, pSB
->baseVertexIndex
);
431 if (pSB
->Set
.material
&& pSB
->Changed
.material
)
432 IDirect3DDevice8Impl_SetMaterial(iface
, &pSB
->material
);
434 if (pSB
->Set
.viewport
&& pSB
->Changed
.viewport
)
435 IDirect3DDevice8Impl_SetViewport(iface
, &pSB
->viewport
);
437 for (i
=0; i
<MAX_STREAMS
; i
++) {
438 if (pSB
->Set
.stream_source
[i
] && pSB
->Changed
.stream_source
[i
])
439 IDirect3DDevice8Impl_SetStreamSource(iface
, i
, pSB
->stream_source
[i
], pSB
->stream_stride
[i
]);
442 for (i
= 0; i
< GL_LIMITS(clipplanes
); i
++) {
443 if (pSB
->Set
.clipplane
[i
] && pSB
->Changed
.clipplane
[i
]) {
446 clip
[0] = pSB
->clipplane
[i
][0];
447 clip
[1] = pSB
->clipplane
[i
][1];
448 clip
[2] = pSB
->clipplane
[i
][2];
449 clip
[3] = pSB
->clipplane
[i
][3];
450 IDirect3DDevice8Impl_SetClipPlane(iface
, i
, clip
);
455 for (i
= 0; i
< HIGHEST_RENDER_STATE
; i
++) {
456 if (pSB
->Set
.renderstate
[i
] && pSB
->Changed
.renderstate
[i
])
457 IDirect3DDevice8Impl_SetRenderState(iface
, i
, pSB
->renderstate
[i
]);
461 for (j
= 0; j
< GL_LIMITS(textures
); j
++) {
462 for (i
= 0; i
< HIGHEST_TEXTURE_STATE
; i
++) {
463 if (pSB
->Set
.texture_state
[j
][i
] && pSB
->Changed
.texture_state
[j
][i
]) {
464 IDirect3DDevice8Impl_SetTextureStageState(iface
, j
, i
, pSB
->texture_state
[j
][i
]);
467 if (pSB
->Set
.textures
[j
] && pSB
->Changed
.textures
[j
]) {
468 IDirect3DDevice8Impl_SetTexture(iface
, j
, pSB
->textures
[j
]);
473 } else if (pSB
->blockType
== D3DSBT_PIXELSTATE
) {
475 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_R
; i
++) {
476 if (pSB
->Set
.renderstate
[SavedPixelStates_R
[i
]] && pSB
->Changed
.renderstate
[SavedPixelStates_R
[i
]])
477 IDirect3DDevice8Impl_SetRenderState(iface
, SavedPixelStates_R
[i
], pSB
->renderstate
[SavedPixelStates_R
[i
]]);
481 for (j
= 0; j
< GL_LIMITS(textures
); i
++) {
482 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_T
; i
++) {
483 if (pSB
->Set
.texture_state
[j
][SavedPixelStates_T
[i
]] &&
484 pSB
->Changed
.texture_state
[j
][SavedPixelStates_T
[i
]])
485 IDirect3DDevice8Impl_SetTextureStageState(iface
, j
, SavedPixelStates_T
[i
], pSB
->texture_state
[j
][SavedPixelStates_T
[i
]]);
489 } else if (pSB
->blockType
== D3DSBT_VERTEXSTATE
) {
491 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_R
; i
++) {
492 if (pSB
->Set
.renderstate
[SavedVertexStates_R
[i
]] && pSB
->Changed
.renderstate
[SavedVertexStates_R
[i
]])
493 IDirect3DDevice8Impl_SetRenderState(iface
, SavedVertexStates_R
[i
], pSB
->renderstate
[SavedVertexStates_R
[i
]]);
496 for (j
= 0; j
< GL_LIMITS(textures
); i
++) {
497 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_T
; i
++) {
498 if (pSB
->Set
.texture_state
[j
][SavedVertexStates_T
[i
]] &&
499 pSB
->Changed
.texture_state
[j
][SavedVertexStates_T
[i
]])
500 IDirect3DDevice8Impl_SetTextureStageState(iface
, j
, SavedVertexStates_T
[i
], pSB
->texture_state
[j
][SavedVertexStates_T
[i
]]);
506 FIXME("Unrecognized state block type %d\n", pSB
->blockType
);
508 memcpy(&This
->StateBlock
->Changed
, &pSB
->Changed
, sizeof(This
->StateBlock
->Changed
));
509 TRACE("(%p) : Applied state block %p ------------------^\n", This
, pSB
);
514 HRESULT WINAPI
IDirect3DDeviceImpl_CaptureStateBlock(IDirect3DDevice8Impl
* This
, IDirect3DStateBlockImpl
* updateBlock
) {
515 LPDIRECT3DDEVICE8 iface
= (LPDIRECT3DDEVICE8
) This
;
517 TRACE("(%p) : Updating state block %p ------------------v \n", This
, updateBlock
);
519 /* If not recorded, then update can just recapture */
520 if (updateBlock
->blockType
!= D3DSBT_RECORDED
) {
521 IDirect3DStateBlockImpl
* tmpBlock
;
522 IDirect3DDeviceImpl_CreateStateBlock(This
, updateBlock
->blockType
, &tmpBlock
);
523 memcpy(updateBlock
, tmpBlock
, sizeof(IDirect3DStateBlockImpl
));
524 IDirect3DDeviceImpl_DeleteStateBlock(This
, tmpBlock
);
526 /* FIXME: This will record states of new lights! May need to have and save set_lights
527 across this action */
532 /* Recorded => Only update 'changed' values */
533 if (updateBlock
->Set
.vertexShader
&& updateBlock
->VertexShader
!= This
->StateBlock
->VertexShader
) {
534 updateBlock
->VertexShader
= This
->StateBlock
->VertexShader
;
535 TRACE("Updating vertex shader to %ld\n", This
->StateBlock
->VertexShader
);
538 /* TODO: Vertex Shader Constants */
540 for (i
= 0; i
< GL_LIMITS(lights
); i
++) {
541 if (updateBlock
->Set
.lightEnable
[i
] && This
->StateBlock
->lightEnable
[i
] != updateBlock
->lightEnable
[i
]) {
542 TRACE("Updating light enable for light %d to %d\n", i
, This
->StateBlock
->lightEnable
[i
]);
543 updateBlock
->lightEnable
[i
] = This
->StateBlock
->lightEnable
[i
];
546 if (updateBlock
->Set
.lights
[i
] && memcmp(&This
->StateBlock
->lights
[i
],
547 &updateBlock
->lights
[i
],
548 sizeof(D3DLIGHT8
)) != 0) {
549 TRACE("Updating lights for light %d\n", i
);
550 memcpy(&updateBlock
->lights
[i
], &This
->StateBlock
->lights
[i
], sizeof(D3DLIGHT8
));
554 if (updateBlock
->Set
.pixelShader
&& updateBlock
->PixelShader
!= This
->StateBlock
->PixelShader
) {
555 TRACE("Updating pixel shader to %ld\n", This
->StateBlock
->PixelShader
);
556 updateBlock
->lights
[i
] = This
->StateBlock
->lights
[i
];
557 IDirect3DDevice8Impl_SetVertexShader(iface
, updateBlock
->PixelShader
);
560 /* TODO: Pixel Shader Constants */
562 /* Others + Render & Texture */
563 for (i
= 0; i
< HIGHEST_TRANSFORMSTATE
; i
++) {
564 if (updateBlock
->Set
.transform
[i
] && memcmp(&This
->StateBlock
->transforms
[i
],
565 &updateBlock
->transforms
[i
],
566 sizeof(D3DMATRIX
)) != 0) {
567 TRACE("Updating transform %d\n", i
);
568 memcpy(&updateBlock
->transforms
[i
], &This
->StateBlock
->transforms
[i
], sizeof(D3DMATRIX
));
572 if (updateBlock
->Set
.Indices
&& ((updateBlock
->pIndexData
!= This
->StateBlock
->pIndexData
)
573 || (updateBlock
->baseVertexIndex
!= This
->StateBlock
->baseVertexIndex
))) {
574 TRACE("Updating pindexData to %p, baseVertexIndex to %d\n",
575 This
->StateBlock
->pIndexData
, This
->StateBlock
->baseVertexIndex
);
576 updateBlock
->pIndexData
= This
->StateBlock
->pIndexData
;
577 updateBlock
->baseVertexIndex
= This
->StateBlock
->baseVertexIndex
;
580 if (updateBlock
->Set
.material
&& memcmp(&This
->StateBlock
->material
,
581 &updateBlock
->material
,
582 sizeof(D3DMATERIAL8
)) != 0) {
583 TRACE("Updating material\n");
584 memcpy(&updateBlock
->material
, &This
->StateBlock
->material
, sizeof(D3DMATERIAL8
));
587 if (updateBlock
->Set
.viewport
&& memcmp(&This
->StateBlock
->viewport
,
588 &updateBlock
->viewport
,
589 sizeof(D3DVIEWPORT8
)) != 0) {
590 TRACE("Updating viewport\n");
591 memcpy(&updateBlock
->viewport
, &This
->StateBlock
->viewport
, sizeof(D3DVIEWPORT8
));
594 for (i
= 0; i
< MAX_STREAMS
; i
++) {
595 if (updateBlock
->Set
.stream_source
[i
] &&
596 ((updateBlock
->stream_stride
[i
] != This
->StateBlock
->stream_stride
[i
]) ||
597 (updateBlock
->stream_source
[i
] != This
->StateBlock
->stream_source
[i
]))) {
598 TRACE("Updating stream source %d to %p, stride to %d\n", i
, This
->StateBlock
->stream_source
[i
],
599 This
->StateBlock
->stream_stride
[i
]);
600 updateBlock
->stream_stride
[i
] = This
->StateBlock
->stream_stride
[i
];
601 updateBlock
->stream_source
[i
] = This
->StateBlock
->stream_source
[i
];
605 for (i
= 0; i
< GL_LIMITS(clipplanes
); i
++) {
606 if (updateBlock
->Set
.clipplane
[i
] && memcmp(&This
->StateBlock
->clipplane
[i
],
607 &updateBlock
->clipplane
[i
],
608 sizeof(updateBlock
->clipplane
)) != 0) {
610 TRACE("Updating clipplane %d\n", i
);
611 memcpy(&updateBlock
->clipplane
[i
], &This
->StateBlock
->clipplane
[i
],
612 sizeof(updateBlock
->clipplane
));
617 for (i
= 0; i
< HIGHEST_RENDER_STATE
; i
++) {
619 if (updateBlock
->Set
.renderstate
[i
] && (updateBlock
->renderstate
[i
] !=
620 This
->StateBlock
->renderstate
[i
])) {
621 TRACE("Updating renderstate %d to %ld\n", i
, This
->StateBlock
->renderstate
[i
]);
622 updateBlock
->renderstate
[i
] = This
->StateBlock
->renderstate
[i
];
627 for (j
= 0; j
< GL_LIMITS(textures
); j
++) {
628 for (i
= 0; i
< HIGHEST_TEXTURE_STATE
; i
++) {
630 if (updateBlock
->Set
.texture_state
[j
][i
] && (updateBlock
->texture_state
[j
][i
] !=
631 This
->StateBlock
->texture_state
[j
][i
])) {
632 TRACE("Updating texturestagestate %d,%d to %ld (was %ld)\n", j
,i
, This
->StateBlock
->texture_state
[j
][i
],
633 updateBlock
->texture_state
[j
][i
]);
634 updateBlock
->texture_state
[j
][i
] = This
->StateBlock
->texture_state
[j
][i
];
637 if (updateBlock
->Set
.textures
[j
] && (updateBlock
->textures
[j
] != This
->StateBlock
->textures
[j
])) {
638 TRACE("Updating texture %d to %p (was %p)\n", j
, This
->StateBlock
->textures
[j
], updateBlock
->textures
[j
]);
639 updateBlock
->textures
[j
] = This
->StateBlock
->textures
[j
];
646 TRACE("(%p) : Updated state block %p ------------------^\n", This
, updateBlock
);
651 DWORD SavedPixelStates_R
[NUM_SAVEDPIXELSTATES_R
] = {
652 D3DRS_ALPHABLENDENABLE
,
655 D3DRS_ALPHATESTENABLE
,
657 D3DRS_COLORWRITEENABLE
,
660 D3DRS_EDGEANTIALIAS
,
669 D3DRS_STENCILENABLE
,
675 D3DRS_STENCILWRITEMASK
,
677 D3DRS_TEXTUREFACTOR
,
692 DWORD SavedPixelStates_T
[NUM_SAVEDPIXELSTATES_T
] = {
701 D3DTSS_BUMPENVLOFFSET
,
702 D3DTSS_BUMPENVLSCALE
,
703 D3DTSS_BUMPENVMAT00
,
704 D3DTSS_BUMPENVMAT01
,
705 D3DTSS_BUMPENVMAT10
,
706 D3DTSS_BUMPENVMAT11
,
712 D3DTSS_MAXANISOTROPY
,
716 D3DTSS_MIPMAPLODBIAS
,
718 D3DTSS_TEXCOORDINDEX
,
719 D3DTSS_TEXTURETRANSFORMFLAGS
722 DWORD SavedVertexStates_R
[NUM_SAVEDVERTEXSTATES_R
] = {
724 D3DRS_AMBIENTMATERIALSOURCE
,
726 D3DRS_CLIPPLANEENABLE
,
728 D3DRS_DIFFUSEMATERIALSOURCE
,
729 D3DRS_EMISSIVEMATERIALSOURCE
,
734 D3DRS_FOGVERTEXMODE
,
735 D3DRS_INDEXEDVERTEXBLENDENABLE
,
738 D3DRS_MULTISAMPLEANTIALIAS
,
739 D3DRS_MULTISAMPLEMASK
,
740 D3DRS_NORMALIZENORMALS
,
741 D3DRS_PATCHEDGESTYLE
,
742 D3DRS_PATCHSEGMENTS
,
746 D3DRS_POINTSCALEENABLE
,
748 D3DRS_POINTSIZE_MAX
,
749 D3DRS_POINTSIZE_MIN
,
750 D3DRS_POINTSPRITEENABLE
,
751 D3DRS_RANGEFOGENABLE
,
752 D3DRS_SOFTWAREVERTEXPROCESSING
,
753 D3DRS_SPECULARMATERIALSOURCE
,
758 DWORD SavedVertexStates_T
[NUM_SAVEDVERTEXSTATES_T
] = {
759 D3DTSS_TEXCOORDINDEX
,
760 D3DTSS_TEXTURETRANSFORMFLAGS