295 lines
15 KiB
C
295 lines
15 KiB
C
/*
|
|
* state block implementation
|
|
*
|
|
* Copyright 2002 Raphael Junqueira
|
|
* 2004 Jason Edmeades
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "wined3d_private.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
|
|
#define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
|
|
|
|
HRESULT WINAPI IWineD3DStateBlockImpl_GetParent(IWineD3DStateBlock *iface, IUnknown **pParent) {
|
|
IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
|
|
IUnknown_AddRef(This->parent);
|
|
*pParent = This->parent;
|
|
return D3D_OK;
|
|
}
|
|
|
|
HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStateBlock* iface) {
|
|
IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
|
|
IWineD3DDeviceImpl *ThisDevice = (IWineD3DDeviceImpl *)(This->wineD3DDevice);
|
|
union {
|
|
D3DLINEPATTERN lp;
|
|
DWORD d;
|
|
} lp;
|
|
union {
|
|
float f;
|
|
DWORD d;
|
|
} tmpfloat;
|
|
unsigned int i;
|
|
|
|
/* Note this may have a large overhead but it should only be executed
|
|
once, in order to initialize the complete state of the device and
|
|
all opengl equivalents */
|
|
TRACE("-----------------------> Setting up device defaults...\n");
|
|
This->blockType = D3DSBT_ALL;
|
|
|
|
/* FIXME: Set some of the defaults for lights, transforms etc */
|
|
memcpy(&This->transforms[D3DTS_PROJECTION], &identity, sizeof(identity));
|
|
memcpy(&This->transforms[D3DTS_VIEW], &identity, sizeof(identity));
|
|
for (i = 0; i < 256; ++i) {
|
|
memcpy(&This->transforms[D3DTS_WORLDMATRIX(i)], &identity, sizeof(identity));
|
|
}
|
|
|
|
/* Render states: */
|
|
if (ThisDevice->presentParms.EnableAutoDepthStencil) {
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_ZENABLE, D3DZB_TRUE);
|
|
} else {
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_ZENABLE, D3DZB_FALSE);
|
|
}
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_FILLMODE, D3DFILL_SOLID);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
|
|
|
|
lp.lp.wRepeatFactor = 0; lp.lp.wLinePattern = 0;
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_LINEPATTERN, lp.d);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_ZWRITEENABLE, TRUE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_ALPHATESTENABLE, FALSE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_LASTPIXEL, TRUE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_SRCBLEND, D3DBLEND_ONE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_DESTBLEND, D3DBLEND_ZERO);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_CULLMODE, D3DCULL_CCW);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_ALPHAFUNC, D3DCMP_ALWAYS);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_ALPHAREF, 0xff); /*??*/
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_DITHERENABLE, FALSE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_ALPHABLENDENABLE, FALSE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_FOGENABLE, FALSE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_SPECULARENABLE, FALSE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_ZVISIBLE, 0);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_FOGCOLOR, 0);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
|
|
tmpfloat.f = 0.0f;
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_FOGSTART, tmpfloat.d);
|
|
tmpfloat.f = 1.0f;
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_FOGEND, tmpfloat.d);
|
|
tmpfloat.f = 1.0f;
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_FOGDENSITY, tmpfloat.d);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_EDGEANTIALIAS, FALSE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_ZBIAS, 0);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_RANGEFOGENABLE, FALSE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_STENCILENABLE, FALSE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
|
|
|
|
/* Setting stencil func also uses values for stencil ref/mask, so manually set defaults
|
|
* so only a single call performed (and ensure defaults initialized before making that call)
|
|
*
|
|
* IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_STENCILREF, 0);
|
|
* IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_STENCILMASK, 0xFFFFFFFF);
|
|
*/
|
|
This->renderState[D3DRS_STENCILREF] = 0;
|
|
This->renderState[D3DRS_STENCILMASK] = 0xFFFFFFFF;
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_STENCILWRITEMASK, 0xFFFFFFFF);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_TEXTUREFACTOR, 0xFFFFFFFF);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_WRAP0, 0);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_WRAP1, 0);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_WRAP2, 0);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_WRAP3, 0);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_WRAP4, 0);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_WRAP5, 0);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_WRAP6, 0);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_WRAP7, 0);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_CLIPPING, TRUE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_LIGHTING, TRUE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_AMBIENT, 0);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_COLORVERTEX, TRUE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_LOCALVIEWER, TRUE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_NORMALIZENORMALS, FALSE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR2);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_VERTEXBLEND, D3DVBF_DISABLE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_CLIPPLANEENABLE, 0);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
|
|
tmpfloat.f = 1.0f;
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_POINTSIZE, tmpfloat.d);
|
|
tmpfloat.f = 0.0f;
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_POINTSIZE_MIN, tmpfloat.d);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_POINTSPRITEENABLE, FALSE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_POINTSCALEENABLE, FALSE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_POINTSCALE_A, TRUE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_POINTSCALE_B, TRUE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_POINTSCALE_C, TRUE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_MULTISAMPLEANTIALIAS, TRUE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE);
|
|
tmpfloat.f = 1.0f;
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_PATCHSEGMENTS, tmpfloat.d);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_DEBUGMONITORTOKEN, D3DDMT_DISABLE);
|
|
tmpfloat.f = 64.0f;
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_POINTSIZE_MAX, tmpfloat.d);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_COLORWRITEENABLE, 0x0000000F);
|
|
tmpfloat.f = 0.0f;
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_TWEENFACTOR, tmpfloat.d);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_POSITIONORDER, D3DORDER_CUBIC);
|
|
IWineD3DDevice_SetRenderState(This->wineD3DDevice, D3DRS_NORMALORDER, D3DORDER_LINEAR);
|
|
|
|
/** clipping status */
|
|
This->clip_status.ClipUnion = 0;
|
|
This->clip_status.ClipIntersection = 0xFFFFFFFF;
|
|
|
|
/* Texture Stage States - Put directly into state block, we will call function below */
|
|
for (i = 0; i < GL_LIMITS(textures); i++) {
|
|
TRACE("Setting up default texture states for texture Stage %d\n", i);
|
|
memcpy(&This->transforms[D3DTS_TEXTURE0 + i], &identity, sizeof(identity));
|
|
This->textureState[i][D3DTSS_COLOROP ] = (i==0)? D3DTOP_MODULATE : D3DTOP_DISABLE;
|
|
This->textureState[i][D3DTSS_COLORARG1 ] = D3DTA_TEXTURE;
|
|
This->textureState[i][D3DTSS_COLORARG2 ] = D3DTA_CURRENT;
|
|
This->textureState[i][D3DTSS_ALPHAOP ] = (i==0)? D3DTOP_SELECTARG1 : D3DTOP_DISABLE;
|
|
This->textureState[i][D3DTSS_ALPHAARG1 ] = D3DTA_TEXTURE;
|
|
This->textureState[i][D3DTSS_ALPHAARG2 ] = D3DTA_CURRENT;
|
|
This->textureState[i][D3DTSS_BUMPENVMAT00 ] = (DWORD) 0.0;
|
|
This->textureState[i][D3DTSS_BUMPENVMAT01 ] = (DWORD) 0.0;
|
|
This->textureState[i][D3DTSS_BUMPENVMAT10 ] = (DWORD) 0.0;
|
|
This->textureState[i][D3DTSS_BUMPENVMAT11 ] = (DWORD) 0.0;
|
|
This->textureState[i][D3DTSS_TEXCOORDINDEX ] = i;
|
|
This->textureState[i][D3DTSS_ADDRESSU ] = D3DTADDRESS_WRAP;
|
|
This->textureState[i][D3DTSS_ADDRESSV ] = D3DTADDRESS_WRAP;
|
|
This->textureState[i][D3DTSS_BORDERCOLOR ] = 0x00;
|
|
This->textureState[i][D3DTSS_MAGFILTER ] = D3DTEXF_POINT;
|
|
This->textureState[i][D3DTSS_MINFILTER ] = D3DTEXF_POINT;
|
|
This->textureState[i][D3DTSS_MIPFILTER ] = D3DTEXF_NONE;
|
|
This->textureState[i][D3DTSS_MIPMAPLODBIAS ] = 0;
|
|
This->textureState[i][D3DTSS_MAXMIPLEVEL ] = 0;
|
|
This->textureState[i][D3DTSS_MAXANISOTROPY ] = 1;
|
|
This->textureState[i][D3DTSS_BUMPENVLSCALE ] = (DWORD) 0.0;
|
|
This->textureState[i][D3DTSS_BUMPENVLOFFSET ] = (DWORD) 0.0;
|
|
This->textureState[i][D3DTSS_TEXTURETRANSFORMFLAGS ] = D3DTTFF_DISABLE;
|
|
This->textureState[i][D3DTSS_ADDRESSW ] = D3DTADDRESS_WRAP;
|
|
This->textureState[i][D3DTSS_COLORARG0 ] = D3DTA_CURRENT;
|
|
This->textureState[i][D3DTSS_ALPHAARG0 ] = D3DTA_CURRENT;
|
|
This->textureState[i][D3DTSS_RESULTARG ] = D3DTA_CURRENT;
|
|
}
|
|
|
|
/* Under DirectX you can have texture stage operations even if no texture is
|
|
bound, whereas opengl will only do texture operations when a valid texture is
|
|
bound. We emulate this by creating dummy textures and binding them to each
|
|
texture stage, but disable all stages by default. Hence if a stage is enabled
|
|
then the default texture will kick in until replaced by a SetTexture call */
|
|
|
|
ENTER_GL();
|
|
|
|
for (i = 0; i < GL_LIMITS(textures); i++) {
|
|
GLubyte white = 255;
|
|
|
|
/* Note this avoids calling settexture, so pretend it has been called */
|
|
This->set.textures[i] = TRUE;
|
|
This->changed.textures[i] = TRUE;
|
|
This->textures[i] = NULL;
|
|
|
|
/* Make appropriate texture active */
|
|
if (GL_SUPPORT(ARB_MULTITEXTURE)) {
|
|
GLACTIVETEXTURE(i);
|
|
} else if (i > 0) {
|
|
FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
|
|
}
|
|
|
|
/* Generate an opengl texture name */
|
|
glGenTextures(1, &ThisDevice->dummyTextureName[i]);
|
|
checkGLcall("glGenTextures");
|
|
TRACE("Dummy Texture %d given name %d\n", i, ThisDevice->dummyTextureName[i]);
|
|
|
|
/* Generate a dummy 1d texture */
|
|
This->textureDimensions[i] = GL_TEXTURE_1D;
|
|
glBindTexture(GL_TEXTURE_1D, ThisDevice->dummyTextureName[i]);
|
|
checkGLcall("glBindTexture");
|
|
|
|
glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &white);
|
|
checkGLcall("glTexImage1D");
|
|
|
|
/* Reapply all the texture state information to this texture */
|
|
IWineD3DDevice_SetupTextureStates(This->wineD3DDevice, i, REAPPLY_ALL);
|
|
}
|
|
|
|
LEAVE_GL();
|
|
|
|
#if 0 /* TODO: Palette support */
|
|
/* defaulting palettes */
|
|
for (i = 0; i < MAX_PALETTES; ++i) {
|
|
int j;
|
|
for (j = 0; j < 256; ++j) {
|
|
This->palettes[i][j].peRed = 0xFF;
|
|
This->palettes[i][j].peGreen = 0xFF;
|
|
This->palettes[i][j].peBlue = 0xFF;
|
|
This->palettes[i][j].peFlags = 0xFF;
|
|
}
|
|
}
|
|
This->currentPalette = 0;
|
|
#endif /* TODO: Palette support */
|
|
|
|
TRACE("-----------------------> Device defaults now set up...\n");
|
|
return D3D_OK;
|
|
}
|
|
|
|
/**********************************************************
|
|
* IUnknown parts follows
|
|
**********************************************************/
|
|
HRESULT WINAPI IWineD3DStateBlockImpl_QueryInterface(IWineD3DStateBlock *iface,REFIID riid,LPVOID *ppobj)
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
ULONG WINAPI IWineD3DStateBlockImpl_AddRef(IWineD3DStateBlock *iface) {
|
|
IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
|
|
TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
|
|
return InterlockedIncrement(&This->ref);
|
|
}
|
|
|
|
ULONG WINAPI IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) {
|
|
IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
|
|
ULONG ref;
|
|
TRACE("(%p) : Releasing from %ld\n", This, This->ref);
|
|
ref = InterlockedDecrement(&This->ref);
|
|
if (ref == 0) {
|
|
IWineD3DDevice_Release(This->wineD3DDevice);
|
|
HeapFree(GetProcessHeap(), 0, This);
|
|
}
|
|
return ref;
|
|
}
|
|
|
|
/**********************************************************
|
|
* IWineD3DStateBlock VTbl follows
|
|
**********************************************************/
|
|
|
|
IWineD3DStateBlockVtbl IWineD3DStateBlock_Vtbl =
|
|
{
|
|
IWineD3DStateBlockImpl_QueryInterface,
|
|
IWineD3DStateBlockImpl_AddRef,
|
|
IWineD3DStateBlockImpl_Release,
|
|
IWineD3DStateBlockImpl_GetParent,
|
|
IWineD3DStateBlockImpl_InitStartupStateBlock
|
|
};
|