2 * state block implementation
4 * Copyright 2002 Raphael Junqueira
5 * Copyright 2004 Jason Edmeades
6 * Copyright 2005 Oliver Stieber
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "wined3d_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
27 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
29 /**********************************************************
30 * IWineD3DStateBlockImpl IUnknown parts follows
31 **********************************************************/
32 HRESULT WINAPI IWineD3DStateBlockImpl_QueryInterface(IWineD3DStateBlock *iface,REFIID riid,LPVOID *ppobj)
34 IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
35 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
36 if (IsEqualGUID(riid, &IID_IUnknown)
37 || IsEqualGUID(riid, &IID_IWineD3DStateBlock)){
38 IUnknown_AddRef(iface);
45 ULONG WINAPI IWineD3DStateBlockImpl_AddRef(IWineD3DStateBlock *iface) {
46 IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
47 ULONG refCount = InterlockedIncrement(&This->ref);
49 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
53 ULONG WINAPI IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) {
54 IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
55 ULONG refCount = InterlockedDecrement(&This->ref);
57 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
60 IWineD3DDevice_Release((IWineD3DDevice *)This->wineD3DDevice);
61 HeapFree(GetProcessHeap(), 0, This);
66 /**********************************************************
67 * IWineD3DStateBlockImpl parts follows
68 **********************************************************/
69 HRESULT WINAPI IWineD3DStateBlockImpl_GetParent(IWineD3DStateBlock *iface, IUnknown **pParent) {
70 IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
71 IUnknown_AddRef(This->parent);
72 *pParent = This->parent;
76 HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStateBlock* iface) {
77 IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
78 IWineD3DDeviceImpl *ThisDevice = (IWineD3DDeviceImpl *)(This->wineD3DDevice);
89 /* Note this may have a large overhead but it should only be executed
90 once, in order to initialize the complete state of the device and
91 all opengl equivalents */
92 TRACE("-----------------------> Setting up device defaults...\n");
93 This->blockType = D3DSBT_ALL;
95 /* FIXME: Set some of the defaults for lights, transforms etc */
96 memcpy(&This->transforms[D3DTS_PROJECTION], &identity, sizeof(identity));
97 memcpy(&This->transforms[D3DTS_VIEW], &identity, sizeof(identity));
98 for (i = 0; i < 256; ++i) {
99 memcpy(&This->transforms[D3DTS_WORLDMATRIX(i)], &identity, sizeof(identity));
103 if (ThisDevice->presentParms.EnableAutoDepthStencil) {
104 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_ZENABLE, D3DZB_TRUE);
106 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_ZENABLE, D3DZB_FALSE);
108 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_FILLMODE, D3DFILL_SOLID);
109 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_SHADEMODE, D3DSHADE_GOURAUD);
111 lp.lp.wRepeatFactor = 0; lp.lp.wLinePattern = 0;
112 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_LINEPATTERN, lp.d);
113 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_ZWRITEENABLE, TRUE);
114 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_ALPHATESTENABLE, FALSE);
115 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_LASTPIXEL, TRUE);
116 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_SRCBLEND, D3DBLEND_ONE);
117 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_DESTBLEND, D3DBLEND_ZERO);
118 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_CULLMODE, D3DCULL_CCW);
119 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_ZFUNC, D3DCMP_LESSEQUAL);
120 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_ALPHAFUNC, D3DCMP_ALWAYS);
121 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_ALPHAREF, 0xff); /*??*/
122 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_DITHERENABLE, FALSE);
123 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_ALPHABLENDENABLE, FALSE);
124 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_FOGENABLE, FALSE);
125 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_SPECULARENABLE, FALSE);
126 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_ZVISIBLE, 0);
127 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_FOGCOLOR, 0);
128 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_FOGTABLEMODE, D3DFOG_NONE);
130 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_FOGSTART, tmpfloat.d);
132 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_FOGEND, tmpfloat.d);
134 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_FOGDENSITY, tmpfloat.d);
135 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_EDGEANTIALIAS, FALSE);
136 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_ZBIAS, 0);
137 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_RANGEFOGENABLE, FALSE);
138 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_STENCILENABLE, FALSE);
139 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
140 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
141 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
143 /* Setting stencil func also uses values for stencil ref/mask, so manually set defaults
144 * so only a single call performed (and ensure defaults initialized before making that call)
146 * IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_STENCILREF, 0);
147 * IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_STENCILMASK, 0xFFFFFFFF);
149 This->renderState[WINED3DRS_STENCILREF] = 0;
150 This->renderState[WINED3DRS_STENCILMASK] = 0xFFFFFFFF;
151 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_STENCILFUNC, D3DCMP_ALWAYS);
152 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_STENCILWRITEMASK, 0xFFFFFFFF);
153 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_TEXTUREFACTOR, 0xFFFFFFFF);
154 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_WRAP0, 0);
155 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_WRAP1, 0);
156 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_WRAP2, 0);
157 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_WRAP3, 0);
158 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_WRAP4, 0);
159 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_WRAP5, 0);
160 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_WRAP6, 0);
161 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_WRAP7, 0);
162 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_CLIPPING, TRUE);
163 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_LIGHTING, TRUE);
164 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_AMBIENT, 0);
165 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_FOGVERTEXMODE, D3DFOG_NONE);
166 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_COLORVERTEX, TRUE);
167 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_LOCALVIEWER, TRUE);
168 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_NORMALIZENORMALS, FALSE);
169 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
170 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
171 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR2);
172 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
173 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_VERTEXBLEND, D3DVBF_DISABLE);
174 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_CLIPPLANEENABLE, 0);
175 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
177 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_POINTSIZE, tmpfloat.d);
179 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_POINTSIZE_MIN, tmpfloat.d);
180 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_POINTSPRITEENABLE, FALSE);
181 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_POINTSCALEENABLE, FALSE);
182 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_POINTSCALE_A, TRUE);
183 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_POINTSCALE_B, TRUE);
184 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_POINTSCALE_C, TRUE);
185 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_MULTISAMPLEANTIALIAS, TRUE);
186 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
187 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE);
189 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_PATCHSEGMENTS, tmpfloat.d);
190 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_DEBUGMONITORTOKEN, D3DDMT_DISABLE);
192 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_POINTSIZE_MAX, tmpfloat.d);
193 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
194 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_COLORWRITEENABLE, 0x0000000F);
196 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_TWEENFACTOR, tmpfloat.d);
197 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_BLENDOP, D3DBLENDOP_ADD);
198 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_POSITIONORDER, WINED3DDEGREE_CUBIC);
199 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, WINED3DRS_NORMALORDER, WINED3DDEGREE_LINEAR);
201 /** clipping status */
202 This->clip_status.ClipUnion = 0;
203 This->clip_status.ClipIntersection = 0xFFFFFFFF;
205 /* Texture Stage States - Put directly into state block, we will call function below */
206 for (i = 0; i < GL_LIMITS(textures); i++) {
207 TRACE("Setting up default texture states for texture Stage %d\n", i);
208 memcpy(&This->transforms[D3DTS_TEXTURE0 + i], &identity, sizeof(identity));
209 This->textureState[i][D3DTSS_COLOROP ] = (i==0)? D3DTOP_MODULATE : D3DTOP_DISABLE;
210 This->textureState[i][D3DTSS_COLORARG1 ] = D3DTA_TEXTURE;
211 This->textureState[i][D3DTSS_COLORARG2 ] = D3DTA_CURRENT;
212 This->textureState[i][D3DTSS_ALPHAOP ] = (i==0)? D3DTOP_SELECTARG1 : D3DTOP_DISABLE;
213 This->textureState[i][D3DTSS_ALPHAARG1 ] = D3DTA_TEXTURE;
214 This->textureState[i][D3DTSS_ALPHAARG2 ] = D3DTA_CURRENT;
215 This->textureState[i][D3DTSS_BUMPENVMAT00 ] = (DWORD) 0.0;
216 This->textureState[i][D3DTSS_BUMPENVMAT01 ] = (DWORD) 0.0;
217 This->textureState[i][D3DTSS_BUMPENVMAT10 ] = (DWORD) 0.0;
218 This->textureState[i][D3DTSS_BUMPENVMAT11 ] = (DWORD) 0.0;
219 This->textureState[i][D3DTSS_TEXCOORDINDEX ] = i;
220 This->textureState[i][D3DTSS_ADDRESSU ] = D3DTADDRESS_WRAP;
221 This->textureState[i][D3DTSS_ADDRESSV ] = D3DTADDRESS_WRAP;
222 This->textureState[i][D3DTSS_BORDERCOLOR ] = 0x00;
223 This->textureState[i][D3DTSS_MAGFILTER ] = D3DTEXF_POINT;
224 This->textureState[i][D3DTSS_MINFILTER ] = D3DTEXF_POINT;
225 This->textureState[i][D3DTSS_MIPFILTER ] = D3DTEXF_NONE;
226 This->textureState[i][D3DTSS_MIPMAPLODBIAS ] = 0;
227 This->textureState[i][D3DTSS_MAXMIPLEVEL ] = 0;
228 This->textureState[i][D3DTSS_MAXANISOTROPY ] = 1;
229 This->textureState[i][D3DTSS_BUMPENVLSCALE ] = (DWORD) 0.0;
230 This->textureState[i][D3DTSS_BUMPENVLOFFSET ] = (DWORD) 0.0;
231 This->textureState[i][D3DTSS_TEXTURETRANSFORMFLAGS ] = D3DTTFF_DISABLE;
232 This->textureState[i][D3DTSS_ADDRESSW ] = D3DTADDRESS_WRAP;
233 This->textureState[i][D3DTSS_COLORARG0 ] = D3DTA_CURRENT;
234 This->textureState[i][D3DTSS_ALPHAARG0 ] = D3DTA_CURRENT;
235 This->textureState[i][D3DTSS_RESULTARG ] = D3DTA_CURRENT;
238 /* Under DirectX you can have texture stage operations even if no texture is
239 bound, whereas opengl will only do texture operations when a valid texture is
240 bound. We emulate this by creating dummy textures and binding them to each
241 texture stage, but disable all stages by default. Hence if a stage is enabled
242 then the default texture will kick in until replaced by a SetTexture call */
246 for (i = 0; i < GL_LIMITS(textures); i++) {
249 /* Note this avoids calling settexture, so pretend it has been called */
250 This->set.textures[i] = TRUE;
251 This->changed.textures[i] = TRUE;
252 This->textures[i] = NULL;
254 /* Make appropriate texture active */
255 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
258 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
261 /* Generate an opengl texture name */
262 glGenTextures(1, &ThisDevice->dummyTextureName[i]);
263 checkGLcall("glGenTextures");
264 TRACE("Dummy Texture %d given name %d\n", i, ThisDevice->dummyTextureName[i]);
266 /* Generate a dummy 1d texture */
267 This->textureDimensions[i] = GL_TEXTURE_1D;
268 glBindTexture(GL_TEXTURE_1D, ThisDevice->dummyTextureName[i]);
269 checkGLcall("glBindTexture");
271 glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &white);
272 checkGLcall("glTexImage1D");
274 /* Reapply all the texture state information to this texture */
275 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This->wineD3DDevice, i, REAPPLY_ALL);
280 /* Defaulting palettes - Note these are device wide but reinitialized here for convenience*/
281 for (i = 0; i < MAX_PALETTES; ++i) {
283 for (j = 0; j < 256; ++j) {
284 This->wineD3DDevice->palettes[i][j].peRed = 0xFF;
285 This->wineD3DDevice->palettes[i][j].peGreen = 0xFF;
286 This->wineD3DDevice->palettes[i][j].peBlue = 0xFF;
287 This->wineD3DDevice->palettes[i][j].peFlags = 0xFF;
290 This->wineD3DDevice->currentPalette = 0;
292 TRACE("-----------------------> Device defaults now set up...\n");
296 /**********************************************************
297 * IWineD3DStateBlock VTbl follows
298 **********************************************************/
300 IWineD3DStateBlockVtbl IWineD3DStateBlock_Vtbl =
302 IWineD3DStateBlockImpl_QueryInterface,
303 IWineD3DStateBlockImpl_AddRef,
304 IWineD3DStateBlockImpl_Release,
305 IWineD3DStateBlockImpl_GetParent,
306 IWineD3DStateBlockImpl_InitStartupStateBlock