Use Interlocked* functions in AddRef and Release.
[wine/multimedia.git] / dlls / wined3d / stateblock.c
blob1d447e66e3e924bd3539c2460eedc1f1d4b05ca8
1 /*
2 * state block implementation
4 * Copyright 2002 Raphael Junqueira
5 * 2004 Jason Edmeades
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "config.h"
23 #include "wined3d_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
26 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
28 HRESULT WINAPI IWineD3DStateBlockImpl_GetParent(IWineD3DStateBlock *iface, IUnknown **pParent) {
29 IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
30 IUnknown_AddRef(This->parent);
31 *pParent = This->parent;
32 return D3D_OK;
35 HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStateBlock* iface) {
36 IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
37 IWineD3DDeviceImpl *ThisDevice = (IWineD3DDeviceImpl *)(This->wineD3DDevice);
38 union {
39 D3DLINEPATTERN lp;
40 DWORD d;
41 } lp;
42 union {
43 float f;
44 DWORD d;
45 } tmpfloat;
46 unsigned int i;
48 /* Note this may have a large overhead but it should only be executed
49 once, in order to initialize the complete state of the device and
50 all opengl equivalents */
51 TRACE("-----------------------> Setting up device defaults...\n");
52 This->blockType = D3DSBT_ALL;
54 /* FIXME: Set some of the defaults for lights, transforms etc */
55 memcpy(&This->transforms[D3DTS_PROJECTION], &identity, sizeof(identity));
56 memcpy(&This->transforms[D3DTS_VIEW], &identity, sizeof(identity));
57 for (i = 0; i < 256; ++i) {
58 memcpy(&This->transforms[D3DTS_WORLDMATRIX(i)], &identity, sizeof(identity));
61 /* Render states: */
62 if (ThisDevice->presentParms.EnableAutoDepthStencil) {
63 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_ZENABLE, D3DZB_TRUE);
64 } else {
65 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_ZENABLE, D3DZB_FALSE);
67 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_FILLMODE, D3DFILL_SOLID);
68 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
70 lp.lp.wRepeatFactor = 0; lp.lp.wLinePattern = 0;
71 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_LINEPATTERN, lp.d);
72 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_ZWRITEENABLE, TRUE);
73 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_ALPHATESTENABLE, FALSE);
74 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_LASTPIXEL, TRUE);
75 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_SRCBLEND, D3DBLEND_ONE);
76 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_DESTBLEND, D3DBLEND_ZERO);
77 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_CULLMODE, D3DCULL_CCW);
78 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
79 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_ALPHAFUNC, D3DCMP_ALWAYS);
80 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_ALPHAREF, 0xff); /*??*/
81 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_DITHERENABLE, FALSE);
82 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_ALPHABLENDENABLE, FALSE);
83 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_FOGENABLE, FALSE);
84 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_SPECULARENABLE, FALSE);
85 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_ZVISIBLE, 0);
86 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_FOGCOLOR, 0);
87 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
88 tmpfloat.f = 0.0f;
89 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_FOGSTART, tmpfloat.d);
90 tmpfloat.f = 1.0f;
91 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_FOGEND, tmpfloat.d);
92 tmpfloat.f = 1.0f;
93 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_FOGDENSITY, tmpfloat.d);
94 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_EDGEANTIALIAS, FALSE);
95 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_ZBIAS, 0);
96 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_RANGEFOGENABLE, FALSE);
97 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_STENCILENABLE, FALSE);
98 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
99 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
100 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
102 /* Setting stencil func also uses values for stencil ref/mask, so manually set defaults
103 * so only a single call performed (and ensure defaults initialized before making that call)
105 * IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_STENCILREF, 0);
106 * IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_STENCILMASK, 0xFFFFFFFF);
108 This->renderState[D3DRS_STENCILREF] = 0;
109 This->renderState[D3DRS_STENCILMASK] = 0xFFFFFFFF;
110 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
111 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_STENCILWRITEMASK, 0xFFFFFFFF);
112 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_TEXTUREFACTOR, 0xFFFFFFFF);
113 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_WRAP0, 0);
114 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_WRAP1, 0);
115 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_WRAP2, 0);
116 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_WRAP3, 0);
117 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_WRAP4, 0);
118 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_WRAP5, 0);
119 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_WRAP6, 0);
120 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_WRAP7, 0);
121 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_CLIPPING, TRUE);
122 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_LIGHTING, TRUE);
123 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_AMBIENT, 0);
124 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
125 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_COLORVERTEX, TRUE);
126 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_LOCALVIEWER, TRUE);
127 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_NORMALIZENORMALS, FALSE);
128 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
129 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
130 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR2);
131 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
132 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_VERTEXBLEND, D3DVBF_DISABLE);
133 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_CLIPPLANEENABLE, 0);
134 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
135 tmpfloat.f = 1.0f;
136 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_POINTSIZE, tmpfloat.d);
137 tmpfloat.f = 0.0f;
138 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_POINTSIZE_MIN, tmpfloat.d);
139 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_POINTSPRITEENABLE, FALSE);
140 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_POINTSCALEENABLE, FALSE);
141 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_POINTSCALE_A, TRUE);
142 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_POINTSCALE_B, TRUE);
143 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_POINTSCALE_C, TRUE);
144 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_MULTISAMPLEANTIALIAS, TRUE);
145 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
146 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE);
147 tmpfloat.f = 1.0f;
148 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_PATCHSEGMENTS, tmpfloat.d);
149 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_DEBUGMONITORTOKEN, D3DDMT_DISABLE);
150 tmpfloat.f = 64.0f;
151 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_POINTSIZE_MAX, tmpfloat.d);
152 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
153 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_COLORWRITEENABLE, 0x0000000F);
154 tmpfloat.f = 0.0f;
155 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_TWEENFACTOR, tmpfloat.d);
156 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_BLENDOP, D3DBLENDOP_ADD);
157 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_POSITIONORDER, D3DORDER_CUBIC);
158 IWineD3DDevice_SetRenderState((IWineD3DDevice *)This->wineD3DDevice, D3DRS_NORMALORDER, D3DORDER_LINEAR);
160 /** clipping status */
161 This->clip_status.ClipUnion = 0;
162 This->clip_status.ClipIntersection = 0xFFFFFFFF;
164 /* Texture Stage States - Put directly into state block, we will call function below */
165 for (i = 0; i < GL_LIMITS(textures); i++) {
166 TRACE("Setting up default texture states for texture Stage %d\n", i);
167 memcpy(&This->transforms[D3DTS_TEXTURE0 + i], &identity, sizeof(identity));
168 This->textureState[i][D3DTSS_COLOROP ] = (i==0)? D3DTOP_MODULATE : D3DTOP_DISABLE;
169 This->textureState[i][D3DTSS_COLORARG1 ] = D3DTA_TEXTURE;
170 This->textureState[i][D3DTSS_COLORARG2 ] = D3DTA_CURRENT;
171 This->textureState[i][D3DTSS_ALPHAOP ] = (i==0)? D3DTOP_SELECTARG1 : D3DTOP_DISABLE;
172 This->textureState[i][D3DTSS_ALPHAARG1 ] = D3DTA_TEXTURE;
173 This->textureState[i][D3DTSS_ALPHAARG2 ] = D3DTA_CURRENT;
174 This->textureState[i][D3DTSS_BUMPENVMAT00 ] = (DWORD) 0.0;
175 This->textureState[i][D3DTSS_BUMPENVMAT01 ] = (DWORD) 0.0;
176 This->textureState[i][D3DTSS_BUMPENVMAT10 ] = (DWORD) 0.0;
177 This->textureState[i][D3DTSS_BUMPENVMAT11 ] = (DWORD) 0.0;
178 This->textureState[i][D3DTSS_TEXCOORDINDEX ] = i;
179 This->textureState[i][D3DTSS_ADDRESSU ] = D3DTADDRESS_WRAP;
180 This->textureState[i][D3DTSS_ADDRESSV ] = D3DTADDRESS_WRAP;
181 This->textureState[i][D3DTSS_BORDERCOLOR ] = 0x00;
182 This->textureState[i][D3DTSS_MAGFILTER ] = D3DTEXF_POINT;
183 This->textureState[i][D3DTSS_MINFILTER ] = D3DTEXF_POINT;
184 This->textureState[i][D3DTSS_MIPFILTER ] = D3DTEXF_NONE;
185 This->textureState[i][D3DTSS_MIPMAPLODBIAS ] = 0;
186 This->textureState[i][D3DTSS_MAXMIPLEVEL ] = 0;
187 This->textureState[i][D3DTSS_MAXANISOTROPY ] = 1;
188 This->textureState[i][D3DTSS_BUMPENVLSCALE ] = (DWORD) 0.0;
189 This->textureState[i][D3DTSS_BUMPENVLOFFSET ] = (DWORD) 0.0;
190 This->textureState[i][D3DTSS_TEXTURETRANSFORMFLAGS ] = D3DTTFF_DISABLE;
191 This->textureState[i][D3DTSS_ADDRESSW ] = D3DTADDRESS_WRAP;
192 This->textureState[i][D3DTSS_COLORARG0 ] = D3DTA_CURRENT;
193 This->textureState[i][D3DTSS_ALPHAARG0 ] = D3DTA_CURRENT;
194 This->textureState[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 */
203 ENTER_GL();
205 for (i = 0; i < GL_LIMITS(textures); i++) {
206 GLubyte white = 255;
208 /* Note this avoids calling settexture, so pretend it has been called */
209 This->set.textures[i] = TRUE;
210 This->changed.textures[i] = TRUE;
211 This->textures[i] = NULL;
213 /* Make appropriate texture active */
214 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
215 GLACTIVETEXTURE(i);
216 } else if (i > 0) {
217 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
220 /* Generate an opengl texture name */
221 glGenTextures(1, &ThisDevice->dummyTextureName[i]);
222 checkGLcall("glGenTextures");
223 TRACE("Dummy Texture %d given name %d\n", i, ThisDevice->dummyTextureName[i]);
225 /* Generate a dummy 1d texture */
226 This->textureDimensions[i] = GL_TEXTURE_1D;
227 glBindTexture(GL_TEXTURE_1D, ThisDevice->dummyTextureName[i]);
228 checkGLcall("glBindTexture");
230 glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &white);
231 checkGLcall("glTexImage1D");
233 /* Reapply all the texture state information to this texture */
234 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This->wineD3DDevice, i, REAPPLY_ALL);
237 LEAVE_GL();
239 /* Defaulting palettes - Note these are device wide but reinitialized here for convenience*/
240 for (i = 0; i < MAX_PALETTES; ++i) {
241 int j;
242 for (j = 0; j < 256; ++j) {
243 This->wineD3DDevice->palettes[i][j].peRed = 0xFF;
244 This->wineD3DDevice->palettes[i][j].peGreen = 0xFF;
245 This->wineD3DDevice->palettes[i][j].peBlue = 0xFF;
246 This->wineD3DDevice->palettes[i][j].peFlags = 0xFF;
249 This->wineD3DDevice->currentPalette = 0;
251 TRACE("-----------------------> Device defaults now set up...\n");
252 return D3D_OK;
255 /**********************************************************
256 * IUnknown parts follows
257 **********************************************************/
258 HRESULT WINAPI IWineD3DStateBlockImpl_QueryInterface(IWineD3DStateBlock *iface,REFIID riid,LPVOID *ppobj)
260 return E_NOINTERFACE;
263 ULONG WINAPI IWineD3DStateBlockImpl_AddRef(IWineD3DStateBlock *iface) {
264 IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
265 ULONG refCount = InterlockedIncrement(&This->ref);
267 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
268 return refCount;
271 ULONG WINAPI IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) {
272 IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
273 ULONG refCount = InterlockedDecrement(&This->ref);
275 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
277 if (!refCount) {
278 IWineD3DDevice_Release((IWineD3DDevice *)This->wineD3DDevice);
279 HeapFree(GetProcessHeap(), 0, This);
281 return refCount;
284 /**********************************************************
285 * IWineD3DStateBlock VTbl follows
286 **********************************************************/
288 IWineD3DStateBlockVtbl IWineD3DStateBlock_Vtbl =
290 IWineD3DStateBlockImpl_QueryInterface,
291 IWineD3DStateBlockImpl_AddRef,
292 IWineD3DStateBlockImpl_Release,
293 IWineD3DStateBlockImpl_GetParent,
294 IWineD3DStateBlockImpl_InitStartupStateBlock