📄 state.c
字号:
break;
case WINED3DBLEND_BOTHSRCALPHA : dstBlend = GL_SRC_ALPHA;
srcBlend = GL_SRC_ALPHA;
break;
case WINED3DBLEND_BOTHINVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
srcBlend = GL_ONE_MINUS_SRC_ALPHA;
break;
case WINED3DBLEND_BLENDFACTOR : dstBlend = GL_CONSTANT_COLOR; break;
case WINED3DBLEND_INVBLENDFACTOR : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
default:
FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
}
if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
glEnable(GL_LINE_SMOOTH);
checkGLcall("glEnable(GL_LINE_SMOOTH)");
if(srcBlend != GL_SRC_ALPHA) {
WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n");
}
if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) {
WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n");
}
} else {
glDisable(GL_LINE_SMOOTH);
checkGLcall("glDisable(GL_LINE_SMOOTH)");
}
TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
glBlendFunc(srcBlend, dstBlend);
checkGLcall("glBlendFunc");
}
static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
float col[4];
TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
GL_EXTCALL(glBlendColor (col[0],col[1],col[2],col[3]));
checkGLcall("glBlendColor");
}
static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
int glParm = 0;
float ref;
BOOL enable_ckey = FALSE;
IWineD3DSurfaceImpl *surf;
/* Find out if the texture on the first stage has a ckey set
* The alpha state func reads the texture settings, even though alpha and texture are not grouped
* together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
* used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
* in case it finds some texture+colorkeyenable combination which needs extra care.
*/
if(stateblock->textures[0] && stateblock->textureDimensions[0] == GL_TEXTURE_2D) {
surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
if(surf->CKeyFlags & WINEDDSD_CKSRCBLT) {
const StaticPixelFormatDesc *fmt = getFormatDescEntry(surf->resource.format, NULL, NULL);
/* The surface conversion does not do color keying conversion for surfaces that have an alpha
* channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
* surface has alpha bits
*/
if(fmt->alphaMask == 0x00000000) {
enable_ckey = TRUE;
}
}
}
if(enable_ckey || context->last_was_ckey) {
StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
}
context->last_was_ckey = enable_ckey;
if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
glEnable(GL_ALPHA_TEST);
checkGLcall("glEnable GL_ALPHA_TEST");
} else {
glDisable(GL_ALPHA_TEST);
checkGLcall("glDisable GL_ALPHA_TEST");
/* Alpha test is disabled, don't bother setting the params - it will happen on the next
* enable call
*/
return;
}
if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
glParm = GL_NOTEQUAL;
ref = 0.0;
} else {
ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
}
if(glParm) {
glAlphaFunc(glParm, ref);
checkGLcall("glAlphaFunc");
}
}
static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
DWORD enable = 0xFFFFFFFF;
DWORD disable = 0x00000000;
if (use_vs(stateblock->wineD3DDevice)) {
/* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
* so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
* contitions I got sick of tracking down. The shader state handler disables all clip planes because
* of that - don't do anything here and keep them disabled
*/
if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
static BOOL warned = FALSE;
if(!warned) {
FIXME("Clipping not supported with vertex shaders\n");
warned = TRUE;
}
}
return;
}
/* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
* of already set values
*/
/* If enabling / disabling all
* TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
*/
if (stateblock->renderState[WINED3DRS_CLIPPING]) {
enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
} else {
disable = 0xffffffff;
enable = 0x00;
}
if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
/** update clipping status */
if (enable) {
stateblock->clip_status.ClipUnion = 0;
stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
} else {
stateblock->clip_status.ClipUnion = 0;
stateblock->clip_status.ClipIntersection = 0;
}
}
static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
int glParm = GL_FUNC_ADD;
if(!GL_SUPPORT(EXT_BLEND_MINMAX)) {
WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
return;
}
switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
case WINED3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
case WINED3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
case WINED3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
case WINED3DBLENDOP_MIN : glParm = GL_MIN; break;
case WINED3DBLENDOP_MAX : glParm = GL_MAX; break;
default:
FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
}
TRACE("glBlendEquation(%x)\n", glParm);
GL_EXTCALL(glBlendEquation(glParm));
checkGLcall("glBlendEquation");
}
static void
state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
/* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
* and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
* specular color. This is wrong:
* Separate specular color means the specular colour is maintained separately, whereas
* single color means it is merged in. However in both cases they are being used to
* some extent.
* To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
* NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
* running 1.4 yet!
*
*
* If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
* Instead, we need to setup the FinalCombiner properly.
*
* The default setup for the FinalCombiner is:
*
* <variable> <input> <mapping> <usage>
* GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
* GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
* GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
* GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
* GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
* GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
* GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
*
* That's pretty much fine as it is, except for variable B, which needs to take
* either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
* whether WINED3DRS_SPECULARENABLE is enabled or not.
*/
TRACE("Setting specular enable state and materials\n");
if (stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular);
checkGLcall("glMaterialfv");
if(stateblock->material.Power > 128.0) {
/* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
* and 128.0, although in d3d neither -1 nor 129 produce an error. For values > 128 clamp
* them, since 128 results in a hardly visible specular highlight, so it should be safe to
* to clamp to 128
*/
WARN("Material power > 128\n");
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 128.0);
} else {
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power);
}
checkGLcall("glMaterialf(GL_SHININESS");
if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
glEnable(GL_COLOR_SUM_EXT);
} else {
TRACE("Specular colors cannot be enabled in this version of opengl\n");
}
checkGLcall("glEnable(GL_COLOR_SUM)");
if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
checkGLcall("glFinalCombinerInputNV()");
}
} else {
float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
/* for the case of enabled lighting: */
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
checkGLcall("glMaterialfv");
/* for the case of disabled lighting: */
if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
glDisable(GL_COLOR_SUM_EXT);
} else {
TRACE("Specular colors cannot be disabled in this version of opengl\n");
}
checkGLcall("glDisable(GL_COLOR_SUM)");
if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
checkGLcall("glFinalCombinerInputNV()");
}
}
TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Diffuse.r, stateblock->material.Diffuse.g,
stateblock->material.Diffuse.b, stateblock->material.Diffuse.a);
TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Ambient.r, stateblock->material.Ambient.g,
stateblock->material.Ambient.b, stateblock->material.Ambient.a);
TRACE("(%p) : Specular (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Specular.r, stateblock->material.Specular.g,
stateblock->material.Specular.b, stateblock->material.Specular.a);
TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Emissive.r, stateblock->material.Emissive.g,
stateblock->material.Emissive.b, stateblock->material.Emissive.a);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &stateblock->material.Ambient);
checkGLcall("glMaterialfv(GL_AMBIENT)");
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &stateblock->material.Diffuse);
checkGLcall("glMaterialfv(GL_DIFFUSE)");
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &stateblock->material.Emissive);
checkGLcall("glMaterialfv(GL_EMISSION)");
}
static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
unsigned int i;
/* Note the texture color applies to all textures whereas
* GL_TEXTURE_ENV_COLOR applies to active only
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -