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 float tmpfloat
= 0.0f
;
61 LPDIRECT3DDEVICE8 iface
= (LPDIRECT3DDEVICE8
) This
;
63 /* Note this may have a large overhead but it should only be executed
64 once, in order to initialize the complete state of the device and
65 all opengl equivalents */
66 TRACE("-----------------------> Setting up device defaults...\n");
67 This
->StateBlock
->blockType
= D3DSBT_ALL
;
69 /* FIXME: Set some of the defaults for lights, transforms etc */
70 memcpy(&This
->StateBlock
->transforms
[D3DTS_PROJECTION
], &idmatrix
, sizeof(idmatrix
));
71 memcpy(&This
->StateBlock
->transforms
[D3DTS_VIEW
], &idmatrix
, sizeof(idmatrix
));
72 for (i
= 0; i
< 256; ++i
) {
73 memcpy(&This
->StateBlock
->transforms
[D3DTS_WORLDMATRIX(i
)], &idmatrix
, sizeof(idmatrix
));
77 if (This
->PresentParms
.EnableAutoDepthStencil
) {
78 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZENABLE
, D3DZB_TRUE
);
80 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZENABLE
, D3DZB_FALSE
);
82 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FILLMODE
, D3DFILL_SOLID
);
83 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SHADEMODE
, D3DSHADE_GOURAUD
);
84 lp
.wRepeatFactor
= 0; lp
.wLinePattern
= 0; IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_LINEPATTERN
, *(DWORD
*)&lp
);
85 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZWRITEENABLE
, TRUE
);
86 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ALPHATESTENABLE
, FALSE
);
87 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_LASTPIXEL
, TRUE
);
88 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SRCBLEND
, D3DBLEND_ONE
);
89 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_DESTBLEND
, D3DBLEND_ZERO
);
90 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_CULLMODE
, D3DCULL_CCW
);
91 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZFUNC
, D3DCMP_LESSEQUAL
);
92 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ALPHAFUNC
, D3DCMP_ALWAYS
);
93 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ALPHAREF
, 0xff); /*??*/
94 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_DITHERENABLE
, FALSE
);
95 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ALPHABLENDENABLE
, FALSE
);
96 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGENABLE
, FALSE
);
97 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SPECULARENABLE
, FALSE
);
98 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZVISIBLE
, 0);
99 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGCOLOR
, 0);
100 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGTABLEMODE
, D3DFOG_NONE
);
101 tmpfloat
= 0.0f
; IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGSTART
, *((DWORD
*)&tmpfloat
));
102 tmpfloat
= 1.0f
; IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGEND
, *((DWORD
*)&tmpfloat
));
103 tmpfloat
= 1.0f
; IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGDENSITY
, *((DWORD
*)&tmpfloat
));
104 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_EDGEANTIALIAS
, FALSE
);
105 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_ZBIAS
, 0);
106 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_RANGEFOGENABLE
, FALSE
);
107 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILENABLE
, FALSE
);
108 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILFAIL
, D3DSTENCILOP_KEEP
);
109 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILZFAIL
, D3DSTENCILOP_KEEP
);
110 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILPASS
, D3DSTENCILOP_KEEP
);
112 /* Setting stencil func also uses values for stencil ref/mask, so manually set defaults
113 * so only a single call performed (and ensure defaults initialized before making that call)
115 * IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILREF, 0);
116 * IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILMASK, 0xFFFFFFFF);
118 This
->StateBlock
->renderstate
[D3DRS_STENCILREF
] = 0;
119 This
->StateBlock
->renderstate
[D3DRS_STENCILMASK
] = 0xFFFFFFFF;
120 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILFUNC
, D3DCMP_ALWAYS
);
121 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_STENCILWRITEMASK
, 0xFFFFFFFF);
122 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_TEXTUREFACTOR
, 0xFFFFFFFF);
123 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP0
, 0);
124 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP1
, 0);
125 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP2
, 0);
126 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP3
, 0);
127 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP4
, 0);
128 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP5
, 0);
129 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP6
, 0);
130 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_WRAP7
, 0);
131 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_CLIPPING
, TRUE
);
132 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_LIGHTING
, TRUE
);
133 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_AMBIENT
, 0);
134 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_FOGVERTEXMODE
, D3DFOG_NONE
);
135 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_COLORVERTEX
, TRUE
);
136 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_LOCALVIEWER
, TRUE
);
137 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_NORMALIZENORMALS
, FALSE
);
138 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_DIFFUSEMATERIALSOURCE
, D3DMCS_COLOR1
);
139 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SPECULARMATERIALSOURCE
, D3DMCS_COLOR2
);
140 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_AMBIENTMATERIALSOURCE
, D3DMCS_COLOR2
);
141 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_EMISSIVEMATERIALSOURCE
, D3DMCS_MATERIAL
);
142 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_VERTEXBLEND
, D3DVBF_DISABLE
);
143 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_CLIPPLANEENABLE
, 0);
144 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_SOFTWAREVERTEXPROCESSING
, FALSE
);
145 tmpfloat
= 1.0f
; IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSIZE
, *((DWORD
*)&tmpfloat
));
146 tmpfloat
= 0.0f
; IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSIZE_MIN
, *((DWORD
*)&tmpfloat
));
147 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSPRITEENABLE
, FALSE
);
148 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSCALEENABLE
, FALSE
);
149 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSCALE_A
, TRUE
);
150 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSCALE_B
, TRUE
);
151 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSCALE_C
, TRUE
);
152 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_MULTISAMPLEANTIALIAS
, TRUE
);
153 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_MULTISAMPLEMASK
, 0xFFFFFFFF);
154 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_PATCHEDGESTYLE
, D3DPATCHEDGE_DISCRETE
);
155 tmpfloat
= 1.0f
; IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_PATCHSEGMENTS
, *((DWORD
*)&tmpfloat
));
156 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_DEBUGMONITORTOKEN
, D3DDMT_DISABLE
);
157 tmpfloat
= 64.0f
; IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POINTSIZE_MAX
, (DWORD
) *((DWORD
*)&tmpfloat
));
158 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_INDEXEDVERTEXBLENDENABLE
, FALSE
);
159 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_COLORWRITEENABLE
, 0x0000000F);
160 tmpfloat
= 0.0f
; IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_TWEENFACTOR
, (DWORD
) *((DWORD
*)&tmpfloat
));
161 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_BLENDOP
, D3DBLENDOP_ADD
);
162 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_POSITIONORDER
, D3DORDER_CUBIC
);
163 IDirect3DDevice8Impl_SetRenderState(iface
, D3DRS_NORMALORDER
, D3DORDER_LINEAR
);
165 /* Texture Stage States - Put directly into state block, we will call function below */
166 for (i
= 0; i
< GL_LIMITS(textures
); i
++) {
167 memcpy(&This
->StateBlock
->transforms
[D3DTS_TEXTURE0
+ i
], &idmatrix
, sizeof(idmatrix
));
168 This
->StateBlock
->texture_state
[i
][D3DTSS_COLOROP
] = (i
==0)? D3DTOP_MODULATE
: D3DTOP_DISABLE
;
169 This
->StateBlock
->texture_state
[i
][D3DTSS_COLORARG1
] = D3DTA_TEXTURE
;
170 This
->StateBlock
->texture_state
[i
][D3DTSS_COLORARG2
] = D3DTA_CURRENT
;
171 This
->StateBlock
->texture_state
[i
][D3DTSS_ALPHAOP
] = (i
==0)? D3DTOP_SELECTARG1
: D3DTOP_DISABLE
;
172 This
->StateBlock
->texture_state
[i
][D3DTSS_ALPHAARG1
] = D3DTA_TEXTURE
;
173 This
->StateBlock
->texture_state
[i
][D3DTSS_ALPHAARG2
] = D3DTA_CURRENT
;
174 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVMAT00
] = (DWORD
) 0.0;
175 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVMAT01
] = (DWORD
) 0.0;
176 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVMAT10
] = (DWORD
) 0.0;
177 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVMAT11
] = (DWORD
) 0.0;
178 This
->StateBlock
->texture_state
[i
][D3DTSS_TEXCOORDINDEX
] = i
;
179 This
->StateBlock
->texture_state
[i
][D3DTSS_ADDRESSU
] = D3DTADDRESS_WRAP
;
180 This
->StateBlock
->texture_state
[i
][D3DTSS_ADDRESSV
] = D3DTADDRESS_WRAP
;
181 This
->StateBlock
->texture_state
[i
][D3DTSS_BORDERCOLOR
] = 0x00;
182 This
->StateBlock
->texture_state
[i
][D3DTSS_MAGFILTER
] = D3DTEXF_POINT
;
183 This
->StateBlock
->texture_state
[i
][D3DTSS_MINFILTER
] = D3DTEXF_POINT
;
184 This
->StateBlock
->texture_state
[i
][D3DTSS_MIPFILTER
] = D3DTEXF_NONE
;
185 This
->StateBlock
->texture_state
[i
][D3DTSS_MIPMAPLODBIAS
] = 0;
186 This
->StateBlock
->texture_state
[i
][D3DTSS_MAXMIPLEVEL
] = 0;
187 This
->StateBlock
->texture_state
[i
][D3DTSS_MAXANISOTROPY
] = 1;
188 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVLSCALE
] = (DWORD
) 0.0;
189 This
->StateBlock
->texture_state
[i
][D3DTSS_BUMPENVLOFFSET
] = (DWORD
) 0.0;
190 This
->StateBlock
->texture_state
[i
][D3DTSS_TEXTURETRANSFORMFLAGS
] = D3DTTFF_DISABLE
;
191 This
->StateBlock
->texture_state
[i
][D3DTSS_ADDRESSW
] = D3DTADDRESS_WRAP
;
192 This
->StateBlock
->texture_state
[i
][D3DTSS_COLORARG0
] = D3DTA_CURRENT
;
193 This
->StateBlock
->texture_state
[i
][D3DTSS_ALPHAARG0
] = D3DTA_CURRENT
;
194 This
->StateBlock
->texture_state
[i
][D3DTSS_RESULTARG
] = D3DTA_CURRENT
;
197 /* Under DirectX you can have texture stage operations even if no texture is
198 bound, whereas opengl will only do texture operations when a valid texture is
199 bound. We emulate this by creating dummy textures and binding them to each
200 texture stage, but disable all stages by default. Hence if a stage is enabled
201 then the default texture will kick in until replaced by a SetTexture call */
205 for (i
= 0; i
< GL_LIMITS(textures
); i
++) {
208 /* Note this avoids calling settexture, so pretend it has been called */
209 This
->StateBlock
->Set
.textures
[i
] = TRUE
;
210 This
->StateBlock
->Changed
.textures
[i
] = TRUE
;
211 This
->StateBlock
->textures
[i
] = NULL
;
213 /* Make appropriate texture active */
214 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
215 #if defined(GL_VERSION_1_3)
216 glActiveTexture(GL_TEXTURE0
+ i
);
218 glActiveTextureARB(GL_TEXTURE0_ARB
+ i
);
220 checkGLcall("glActiveTextureARB");
222 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
225 /* Generate an opengl texture name */
226 glGenTextures(1, &This
->dummyTextureName
[i
]);
227 checkGLcall("glGenTextures");
228 TRACE("Dummy Texture %d given name %d\n", i
, This
->dummyTextureName
[i
]);
230 /* Generate a dummy 1d texture */
231 This
->StateBlock
->textureDimensions
[i
] = GL_TEXTURE_1D
;
232 glBindTexture(GL_TEXTURE_1D
, This
->dummyTextureName
[i
]);
233 checkGLcall("glBindTexture");
235 glTexImage1D(GL_TEXTURE_1D
, 0, GL_LUMINANCE
, 1, 0, GL_LUMINANCE
, GL_UNSIGNED_BYTE
, &white
);
236 checkGLcall("glTexImage1D");
238 /* Reapply all the texture state information to this texture */
239 setupTextureStates(iface
, i
, REAPPLY_ALL
);
244 /* defaulting palettes */
245 for (i
= 0; i
< MAX_PALETTES
; ++i
) {
246 for (j
= 0; j
< 256; ++j
) {
247 This
->palettes
[i
][j
].peRed
= 0xFF;
248 This
->palettes
[i
][j
].peGreen
= 0xFF;
249 This
->palettes
[i
][j
].peBlue
= 0xFF;
250 This
->palettes
[i
][j
].peFlags
= 0xFF;
253 This
->currentPalette
= 0;
255 TRACE("-----------------------> Device defaults now set up...\n");
262 HRESULT WINAPI
IDirect3DDeviceImpl_CreateStateBlock(IDirect3DDevice8Impl
* This
, D3DSTATEBLOCKTYPE Type
, IDirect3DStateBlockImpl
** ppStateBlock
) {
263 IDirect3DStateBlockImpl
* object
;
266 TRACE("(%p) : Type(%d)\n", This
, Type
);
268 /* Allocate Storage */
269 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DStateBlockImpl
));
271 if (NULL
== This
->StateBlock
) { /** if it the main stateblock only do init and returns */
272 /*object->lpVtbl = &Direct3DStateBlock9_Vtbl;*/
273 object
->device
= This
;
275 object
->blockType
= Type
;
276 This
->StateBlock
= object
;
277 /* don't forget to init it calling InitStartupStateBlock */
280 memcpy(object
, This
->StateBlock
, sizeof(IDirect3DStateBlockImpl
));
282 *ppStateBlock
= (IDirect3DStateBlockImpl
*) 0xFFFFFFFF;
283 return E_OUTOFMEMORY
;
285 /*object->lpVtbl = &Direct3DStateBlock9_Vtbl;*/
286 object
->device
= This
;
288 object
->blockType
= Type
;
290 TRACE("Updating changed flags appropriate for type %d\n", Type
);
292 if (Type
== D3DSBT_ALL
) {
293 TRACE("ALL => Pretend everything has changed\n");
294 memset(&object
->Changed
, TRUE
, sizeof(This
->StateBlock
->Changed
));
296 } else if (Type
== D3DSBT_PIXELSTATE
) {
298 memset(&object
->Changed
, FALSE
, sizeof(This
->StateBlock
->Changed
));
300 /* TODO: Pixel Shader Constants */
301 object
->Changed
.pixelShader
= TRUE
;
302 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_R
; i
++) {
303 object
->Changed
.renderstate
[SavedPixelStates_R
[i
]] = TRUE
;
305 for (j
= 0; j
< GL_LIMITS(textures
); i
++) {
306 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_T
; i
++) {
307 object
->Changed
.texture_state
[j
][SavedPixelStates_T
[i
]] = TRUE
;
311 } else if (Type
== D3DSBT_VERTEXSTATE
) {
313 memset(&object
->Changed
, FALSE
, sizeof(This
->StateBlock
->Changed
));
315 /* TODO: Vertex Shader Constants */
316 object
->Changed
.vertexShader
= TRUE
;
317 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_R
; i
++) {
318 object
->Changed
.renderstate
[SavedVertexStates_R
[i
]] = TRUE
;
320 for (j
= 0; j
< GL_LIMITS(textures
); i
++) {
321 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_T
; i
++) {
322 object
->Changed
.texture_state
[j
][SavedVertexStates_T
[i
]] = TRUE
;
326 /* Duplicate light chain */
328 PLIGHTINFOEL
*src
= NULL
;
329 PLIGHTINFOEL
*dst
= NULL
;
330 PLIGHTINFOEL
*newEl
= NULL
;
332 src
= This
->StateBlock
->lights
;
333 object
->lights
= NULL
;
336 newEl
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PLIGHTINFOEL
));
337 if (newEl
== NULL
) return D3DERR_OUTOFVIDEOMEMORY
;
338 memcpy(newEl
, src
, sizeof(PLIGHTINFOEL
));
340 newEl
->changed
= TRUE
;
341 newEl
->enabledChanged
= TRUE
;
343 object
->lights
= newEl
;
353 FIXME("Unrecognized state block type %d\n", Type
);
355 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, object
);
357 *ppStateBlock
= object
;
361 /** yakkk temporary waiting for Release */
362 HRESULT WINAPI
IDirect3DDeviceImpl_DeleteStateBlock(IDirect3DDevice8Impl
* This
, IDirect3DStateBlockImpl
* pSB
) {
365 TRACE("(%p) : freeing StateBlock %p\n", This
, pSB
);
367 if (tmp
) tmp
= tmp
->next
;
368 while (tmp
!= NULL
) {
369 HeapFree(GetProcessHeap(), 0, (void *)(tmp
->prev
));
372 if (tmp
) HeapFree(GetProcessHeap(), 0, (void *)tmp
);
373 HeapFree(GetProcessHeap(), 0, (void *)pSB
);
377 HRESULT WINAPI
IDirect3DDeviceImpl_BeginStateBlock(IDirect3DDevice8Impl
* This
) {
378 IDirect3DStateBlockImpl
* object
;
380 TRACE("(%p)\n", This
);
382 if (This
->isRecordingState
) {
383 TRACE("(%p) already recording! returning error\n", This
);
384 return D3DERR_INVALIDCALL
;
387 /* Allocate Storage */
388 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DStateBlockImpl
));
391 return E_OUTOFMEMORY
;
393 /*object->lpVtbl = &Direct3DVextexShaderDeclaration8_Vtbl;*/
394 object
->device
= This
;
397 This
->isRecordingState
= TRUE
;
398 This
->UpdateStateBlock
= object
;
403 HRESULT WINAPI
IDirect3DDeviceImpl_EndStateBlock(IDirect3DDevice8Impl
* This
, IDirect3DStateBlockImpl
** ppStateBlock
) {
404 TRACE("(%p)\n", This
);
406 if (!This
->isRecordingState
) {
407 TRACE("(%p) not recording! returning error\n", This
);
408 *ppStateBlock
= NULL
;
409 return D3DERR_INVALIDCALL
;
412 This
->UpdateStateBlock
->blockType
= D3DSBT_RECORDED
;
413 *ppStateBlock
= This
->UpdateStateBlock
; /* FIXME: AddRef() */
414 This
->isRecordingState
= FALSE
;
415 This
->UpdateStateBlock
= This
->StateBlock
;
417 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, *ppStateBlock
);
421 HRESULT WINAPI
IDirect3DDeviceImpl_ApplyStateBlock(IDirect3DDevice8Impl
* This
, IDirect3DStateBlockImpl
* pSB
) {
424 LPDIRECT3DDEVICE8 iface
= (LPDIRECT3DDEVICE8
) This
;
426 TRACE("(%p) : Applying state block %p ------------------v\n", This
, pSB
);
428 /* FIXME: Only apply applicable states not all states */
430 if (pSB
->blockType
== D3DSBT_RECORDED
|| pSB
->blockType
== D3DSBT_ALL
|| pSB
->blockType
== D3DSBT_VERTEXSTATE
) {
432 PLIGHTINFOEL
*toDo
= pSB
->lights
;
433 while (toDo
!= NULL
) {
435 IDirect3DDevice8Impl_SetLight(iface
, toDo
->OriginalIndex
, &toDo
->OriginalParms
);
436 if (toDo
->enabledChanged
)
437 IDirect3DDevice8Impl_LightEnable(iface
, toDo
->OriginalIndex
, toDo
->lightEnabled
);
441 if (pSB
->Set
.vertexShader
&& pSB
->Changed
.vertexShader
)
442 IDirect3DDevice8Impl_SetVertexShader(iface
, pSB
->VertexShader
);
444 /* TODO: Vertex Shader Constants */
447 if (pSB
->blockType
== D3DSBT_RECORDED
|| pSB
->blockType
== D3DSBT_ALL
|| pSB
->blockType
== D3DSBT_PIXELSTATE
) {
449 if (pSB
->Set
.pixelShader
&& pSB
->Changed
.pixelShader
)
450 IDirect3DDevice8Impl_SetPixelShader(iface
, pSB
->PixelShader
);
452 /* TODO: Pixel Shader Constants */
455 /* Others + Render & Texture */
456 if (pSB
->blockType
== D3DSBT_RECORDED
|| pSB
->blockType
== D3DSBT_ALL
) {
457 for (i
= 0; i
< HIGHEST_TRANSFORMSTATE
; i
++) {
458 if (pSB
->Set
.transform
[i
] && pSB
->Changed
.transform
[i
])
459 IDirect3DDevice8Impl_SetTransform(iface
, i
, &pSB
->transforms
[i
]);
462 if (pSB
->Set
.Indices
&& pSB
->Changed
.Indices
)
463 IDirect3DDevice8Impl_SetIndices(iface
, pSB
->pIndexData
, pSB
->baseVertexIndex
);
465 if (pSB
->Set
.material
&& pSB
->Changed
.material
)
466 IDirect3DDevice8Impl_SetMaterial(iface
, &pSB
->material
);
468 if (pSB
->Set
.viewport
&& pSB
->Changed
.viewport
)
469 IDirect3DDevice8Impl_SetViewport(iface
, &pSB
->viewport
);
471 for (i
=0; i
<MAX_STREAMS
; i
++) {
472 if (pSB
->Set
.stream_source
[i
] && pSB
->Changed
.stream_source
[i
])
473 IDirect3DDevice8Impl_SetStreamSource(iface
, i
, pSB
->stream_source
[i
], pSB
->stream_stride
[i
]);
476 for (i
= 0; i
< GL_LIMITS(clipplanes
); i
++) {
477 if (pSB
->Set
.clipplane
[i
] && pSB
->Changed
.clipplane
[i
]) {
480 clip
[0] = pSB
->clipplane
[i
][0];
481 clip
[1] = pSB
->clipplane
[i
][1];
482 clip
[2] = pSB
->clipplane
[i
][2];
483 clip
[3] = pSB
->clipplane
[i
][3];
484 IDirect3DDevice8Impl_SetClipPlane(iface
, i
, clip
);
489 for (i
= 0; i
< HIGHEST_RENDER_STATE
; i
++) {
490 if (pSB
->Set
.renderstate
[i
] && pSB
->Changed
.renderstate
[i
])
491 IDirect3DDevice8Impl_SetRenderState(iface
, i
, pSB
->renderstate
[i
]);
495 for (j
= 0; j
< GL_LIMITS(textures
); j
++) {
496 for (i
= 0; i
< HIGHEST_TEXTURE_STATE
; i
++) {
497 if (pSB
->Set
.texture_state
[j
][i
] && pSB
->Changed
.texture_state
[j
][i
]) {
498 IDirect3DDevice8Impl_SetTextureStageState(iface
, j
, i
, pSB
->texture_state
[j
][i
]);
501 if (pSB
->Set
.textures
[j
] && pSB
->Changed
.textures
[j
]) {
502 IDirect3DDevice8Impl_SetTexture(iface
, j
, pSB
->textures
[j
]);
507 } else if (pSB
->blockType
== D3DSBT_PIXELSTATE
) {
509 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_R
; i
++) {
510 if (pSB
->Set
.renderstate
[SavedPixelStates_R
[i
]] && pSB
->Changed
.renderstate
[SavedPixelStates_R
[i
]])
511 IDirect3DDevice8Impl_SetRenderState(iface
, SavedPixelStates_R
[i
], pSB
->renderstate
[SavedPixelStates_R
[i
]]);
515 for (j
= 0; j
< GL_LIMITS(textures
); i
++) {
516 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_T
; i
++) {
517 if (pSB
->Set
.texture_state
[j
][SavedPixelStates_T
[i
]] &&
518 pSB
->Changed
.texture_state
[j
][SavedPixelStates_T
[i
]])
519 IDirect3DDevice8Impl_SetTextureStageState(iface
, j
, SavedPixelStates_T
[i
], pSB
->texture_state
[j
][SavedPixelStates_T
[i
]]);
523 } else if (pSB
->blockType
== D3DSBT_VERTEXSTATE
) {
525 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_R
; i
++) {
526 if (pSB
->Set
.renderstate
[SavedVertexStates_R
[i
]] && pSB
->Changed
.renderstate
[SavedVertexStates_R
[i
]])
527 IDirect3DDevice8Impl_SetRenderState(iface
, SavedVertexStates_R
[i
], pSB
->renderstate
[SavedVertexStates_R
[i
]]);
530 for (j
= 0; j
< GL_LIMITS(textures
); i
++) {
531 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_T
; i
++) {
532 if (pSB
->Set
.texture_state
[j
][SavedVertexStates_T
[i
]] &&
533 pSB
->Changed
.texture_state
[j
][SavedVertexStates_T
[i
]])
534 IDirect3DDevice8Impl_SetTextureStageState(iface
, j
, SavedVertexStates_T
[i
], pSB
->texture_state
[j
][SavedVertexStates_T
[i
]]);
540 FIXME("Unrecognized state block type %d\n", pSB
->blockType
);
542 memcpy(&This
->StateBlock
->Changed
, &pSB
->Changed
, sizeof(This
->StateBlock
->Changed
));
543 TRACE("(%p) : Applied state block %p ------------------^\n", This
, pSB
);
548 HRESULT WINAPI
IDirect3DDeviceImpl_CaptureStateBlock(IDirect3DDevice8Impl
* This
, IDirect3DStateBlockImpl
* updateBlock
) {
549 LPDIRECT3DDEVICE8 iface
= (LPDIRECT3DDEVICE8
) This
;
552 TRACE("(%p) : Updating state block %p ------------------v \n", This
, updateBlock
);
554 /* If not recorded, then update can just recapture */
555 if (updateBlock
->blockType
!= D3DSBT_RECORDED
) {
556 IDirect3DStateBlockImpl
* tmpBlock
;
557 IDirect3DDeviceImpl_CreateStateBlock(This
, updateBlock
->blockType
, &tmpBlock
);
559 /* Note just swap the light chains over so when deleting, the old one goes */
560 tmp
= updateBlock
->lights
;
561 memcpy(updateBlock
, tmpBlock
, sizeof(IDirect3DStateBlockImpl
));
562 tmpBlock
->lights
= tmp
;
564 /* Delete the temporary one (which points to the old light chain though */
565 IDirect3DDeviceImpl_DeleteStateBlock(This
, tmpBlock
);
571 /* Recorded => Only update 'changed' values */
572 if (updateBlock
->Set
.vertexShader
&& updateBlock
->VertexShader
!= This
->StateBlock
->VertexShader
) {
573 updateBlock
->VertexShader
= This
->StateBlock
->VertexShader
;
574 TRACE("Updating vertex shader to %ld\n", This
->StateBlock
->VertexShader
);
577 /* TODO: Vertex Shader Constants */
579 /* Lights... For a recorded state block, we just had a chain of actions to perform,
580 so we need to walk that chain and update any actions which differ */
581 src
= updateBlock
->lights
;
582 while (src
!= NULL
) {
583 PLIGHTINFOEL
*realLight
= NULL
;
585 /* Locate the light in the live lights */
586 realLight
= This
->StateBlock
->lights
;
587 while (realLight
!= NULL
&& realLight
->OriginalIndex
!= src
->OriginalIndex
) realLight
= realLight
->next
;
589 if (realLight
== NULL
) {
590 FIXME("A captured light no longer exists...?\n");
593 /* If 'changed' then its a SetLight command. Rather than comparing to see
594 if the OriginalParms have changed and then copy them (twice through
595 memory) just do the copy */
597 TRACE("Updating lights for light %ld\n", src
->OriginalIndex
);
598 memcpy(&src
->OriginalParms
, &realLight
->OriginalParms
, sizeof(PLIGHTINFOEL
));
601 /* If 'enabledChanged' then its a LightEnable command */
602 if (src
->enabledChanged
) {
603 TRACE("Updating lightEnabled for light %ld\n", src
->OriginalIndex
);
604 src
->lightEnabled
= realLight
->lightEnabled
;
613 if (updateBlock
->Set
.pixelShader
&& updateBlock
->PixelShader
!= This
->StateBlock
->PixelShader
) {
614 TRACE("Updating pixel shader to %ld\n", This
->StateBlock
->PixelShader
);
615 IDirect3DDevice8Impl_SetVertexShader(iface
, updateBlock
->PixelShader
);
618 /* TODO: Pixel Shader Constants */
620 /* Others + Render & Texture */
621 for (i
= 0; i
< HIGHEST_TRANSFORMSTATE
; i
++) {
622 if (updateBlock
->Set
.transform
[i
] && memcmp(&This
->StateBlock
->transforms
[i
],
623 &updateBlock
->transforms
[i
],
624 sizeof(D3DMATRIX
)) != 0) {
625 TRACE("Updating transform %d\n", i
);
626 memcpy(&updateBlock
->transforms
[i
], &This
->StateBlock
->transforms
[i
], sizeof(D3DMATRIX
));
630 if (updateBlock
->Set
.Indices
&& ((updateBlock
->pIndexData
!= This
->StateBlock
->pIndexData
)
631 || (updateBlock
->baseVertexIndex
!= This
->StateBlock
->baseVertexIndex
))) {
632 TRACE("Updating pindexData to %p, baseVertexIndex to %d\n",
633 This
->StateBlock
->pIndexData
, This
->StateBlock
->baseVertexIndex
);
634 updateBlock
->pIndexData
= This
->StateBlock
->pIndexData
;
635 updateBlock
->baseVertexIndex
= This
->StateBlock
->baseVertexIndex
;
638 if (updateBlock
->Set
.material
&& memcmp(&This
->StateBlock
->material
,
639 &updateBlock
->material
,
640 sizeof(D3DMATERIAL8
)) != 0) {
641 TRACE("Updating material\n");
642 memcpy(&updateBlock
->material
, &This
->StateBlock
->material
, sizeof(D3DMATERIAL8
));
645 if (updateBlock
->Set
.viewport
&& memcmp(&This
->StateBlock
->viewport
,
646 &updateBlock
->viewport
,
647 sizeof(D3DVIEWPORT8
)) != 0) {
648 TRACE("Updating viewport\n");
649 memcpy(&updateBlock
->viewport
, &This
->StateBlock
->viewport
, sizeof(D3DVIEWPORT8
));
652 for (i
= 0; i
< MAX_STREAMS
; i
++) {
653 if (updateBlock
->Set
.stream_source
[i
] &&
654 ((updateBlock
->stream_stride
[i
] != This
->StateBlock
->stream_stride
[i
]) ||
655 (updateBlock
->stream_source
[i
] != This
->StateBlock
->stream_source
[i
]))) {
656 TRACE("Updating stream source %d to %p, stride to %d\n", i
, This
->StateBlock
->stream_source
[i
],
657 This
->StateBlock
->stream_stride
[i
]);
658 updateBlock
->stream_stride
[i
] = This
->StateBlock
->stream_stride
[i
];
659 updateBlock
->stream_source
[i
] = This
->StateBlock
->stream_source
[i
];
663 for (i
= 0; i
< GL_LIMITS(clipplanes
); i
++) {
664 if (updateBlock
->Set
.clipplane
[i
] && memcmp(&This
->StateBlock
->clipplane
[i
],
665 &updateBlock
->clipplane
[i
],
666 sizeof(updateBlock
->clipplane
)) != 0) {
668 TRACE("Updating clipplane %d\n", i
);
669 memcpy(&updateBlock
->clipplane
[i
], &This
->StateBlock
->clipplane
[i
],
670 sizeof(updateBlock
->clipplane
));
675 for (i
= 0; i
< HIGHEST_RENDER_STATE
; i
++) {
677 if (updateBlock
->Set
.renderstate
[i
] && (updateBlock
->renderstate
[i
] !=
678 This
->StateBlock
->renderstate
[i
])) {
679 TRACE("Updating renderstate %d to %ld\n", i
, This
->StateBlock
->renderstate
[i
]);
680 updateBlock
->renderstate
[i
] = This
->StateBlock
->renderstate
[i
];
685 for (j
= 0; j
< GL_LIMITS(textures
); j
++) {
686 for (i
= 0; i
< HIGHEST_TEXTURE_STATE
; i
++) {
688 if (updateBlock
->Set
.texture_state
[j
][i
] && (updateBlock
->texture_state
[j
][i
] !=
689 This
->StateBlock
->texture_state
[j
][i
])) {
690 TRACE("Updating texturestagestate %d,%d to %ld (was %ld)\n", j
,i
, This
->StateBlock
->texture_state
[j
][i
],
691 updateBlock
->texture_state
[j
][i
]);
692 updateBlock
->texture_state
[j
][i
] = This
->StateBlock
->texture_state
[j
][i
];
695 if (updateBlock
->Set
.textures
[j
] && (updateBlock
->textures
[j
] != This
->StateBlock
->textures
[j
])) {
696 TRACE("Updating texture %d to %p (was %p)\n", j
, This
->StateBlock
->textures
[j
], updateBlock
->textures
[j
]);
697 updateBlock
->textures
[j
] = This
->StateBlock
->textures
[j
];
704 TRACE("(%p) : Updated state block %p ------------------^\n", This
, updateBlock
);
709 DWORD SavedPixelStates_R
[NUM_SAVEDPIXELSTATES_R
] = {
710 D3DRS_ALPHABLENDENABLE
,
713 D3DRS_ALPHATESTENABLE
,
715 D3DRS_COLORWRITEENABLE
,
718 D3DRS_EDGEANTIALIAS
,
727 D3DRS_STENCILENABLE
,
733 D3DRS_STENCILWRITEMASK
,
735 D3DRS_TEXTUREFACTOR
,
750 DWORD SavedPixelStates_T
[NUM_SAVEDPIXELSTATES_T
] = {
759 D3DTSS_BUMPENVLOFFSET
,
760 D3DTSS_BUMPENVLSCALE
,
761 D3DTSS_BUMPENVMAT00
,
762 D3DTSS_BUMPENVMAT01
,
763 D3DTSS_BUMPENVMAT10
,
764 D3DTSS_BUMPENVMAT11
,
770 D3DTSS_MAXANISOTROPY
,
774 D3DTSS_MIPMAPLODBIAS
,
776 D3DTSS_TEXCOORDINDEX
,
777 D3DTSS_TEXTURETRANSFORMFLAGS
780 DWORD SavedVertexStates_R
[NUM_SAVEDVERTEXSTATES_R
] = {
782 D3DRS_AMBIENTMATERIALSOURCE
,
784 D3DRS_CLIPPLANEENABLE
,
786 D3DRS_DIFFUSEMATERIALSOURCE
,
787 D3DRS_EMISSIVEMATERIALSOURCE
,
792 D3DRS_FOGVERTEXMODE
,
793 D3DRS_INDEXEDVERTEXBLENDENABLE
,
796 D3DRS_MULTISAMPLEANTIALIAS
,
797 D3DRS_MULTISAMPLEMASK
,
798 D3DRS_NORMALIZENORMALS
,
799 D3DRS_PATCHEDGESTYLE
,
800 D3DRS_PATCHSEGMENTS
,
804 D3DRS_POINTSCALEENABLE
,
806 D3DRS_POINTSIZE_MAX
,
807 D3DRS_POINTSIZE_MIN
,
808 D3DRS_POINTSPRITEENABLE
,
809 D3DRS_RANGEFOGENABLE
,
810 D3DRS_SOFTWAREVERTEXPROCESSING
,
811 D3DRS_SPECULARMATERIALSOURCE
,
816 DWORD SavedVertexStates_T
[NUM_SAVEDVERTEXSTATES_T
] = {
817 D3DTSS_TEXCOORDINDEX
,
818 D3DTSS_TEXTURETRANSFORMFLAGS