diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h index 024cf66d5eda4179fdd902f1e6f429cb6f20a572..82870d7d73f6de6902e2e6f9421bb440516a5152 100644 --- a/dlls/d3d8/d3d8_private.h +++ b/dlls/d3d8/d3d8_private.h @@ -1283,6 +1283,8 @@ const char* debug_d3dformat(D3DFORMAT fmt); const char* debug_d3dressourcetype(D3DRESOURCETYPE res); const char* debug_d3dprimitivetype(D3DPRIMITIVETYPE PrimitiveType); const char* debug_d3dpool(D3DPOOL Pool); +const char *debug_d3drenderstate(DWORD State); +const char *debug_d3dtexturestate(DWORD State); /* Some #defines for additional diagnostics */ #if 0 /* NOTE: Must be 0 in cvs */ diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index f6f76ad19d6345aa5ef3f7bef05b4c238c46fac7..03115b9d8af77dd31216855be93d49f2733ab91a 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -83,7 +83,20 @@ void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage) { TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage); for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) { - IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]); + + /* Performance: For texture states where multiples effect the outcome, only bother + applying the last one as it will pick up all the other values */ + switch (i) { + case D3DTSS_COLORARG0: /* Will be picked up when setting color op */ + case D3DTSS_COLORARG1: /* Will be picked up when setting color op */ + case D3DTSS_COLORARG2: /* Will be picked up when setting color op */ + case D3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */ + case D3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */ + case D3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */ + break; + default: + IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]); + } } /* Note the D3DRS value applies to all textures, but GL has one @@ -1883,7 +1896,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3 ICOM_THIS(IDirect3DDevice8Impl,iface); DWORD OldValue = This->StateBlock->renderstate[State]; - TRACE("(%p)->state = %d, value = %ld\n", This, State, Value); + TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value); This->UpdateStateBlock->Changed.renderstate[State] = TRUE; This->UpdateStateBlock->Set.renderstate[State] = TRUE; This->UpdateStateBlock->renderstate[State] = Value; @@ -2237,7 +2250,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3 } else { TRACE("Specular colors cannot be enabled in this version of opengl\n"); } - checkGLcall("glEnable(GL_COLOR_SUM)\n"); + checkGLcall("glEnable(GL_COLOR_SUM)"); } else { float black[4] = {0.0f, 0.0f, 0.0f, 0.0f}; @@ -2251,7 +2264,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3 } else { TRACE("Specular colors cannot be disabled in this version of opengl\n"); } - checkGLcall("glDisable(GL_COLOR_SUM)\n"); + checkGLcall("glDisable(GL_COLOR_SUM)"); } } break; @@ -2380,10 +2393,10 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3 { if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) { glEnable(GL_FOG); - checkGLcall("glEnable GL_FOG\n"); + checkGLcall("glEnable GL_FOG"); } else { glDisable(GL_FOG); - checkGLcall("glDisable GL_FOG\n"); + checkGLcall("glDisable GL_FOG"); } } break; @@ -2467,7 +2480,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) { glEnable(GL_COLOR_MATERIAL); - checkGLcall("glEnable GL_GL_COLOR_MATERIAL\n"); + checkGLcall("glEnable GL_COLOR_MATERIAL"); TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n", This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE], @@ -2493,16 +2506,16 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3 if (Parm == -1) { glDisable(GL_COLOR_MATERIAL); - checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n"); + checkGLcall("glDisable GL_COLOR_MATERIAL"); } else { TRACE("glColorMaterial Parm=%d\n", Parm); glColorMaterial(GL_FRONT_AND_BACK, Parm); - checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)\n"); + checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)"); } } else { glDisable(GL_COLOR_MATERIAL); - checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n"); + checkGLcall("glDisable GL_COLOR_MATERIAL"); } } break; @@ -2514,12 +2527,12 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3 if (pattern->wRepeatFactor) { glLineStipple(pattern->wRepeatFactor, pattern->wLinePattern); - checkGLcall("glLineStipple(repeat, linepattern)\n"); + checkGLcall("glLineStipple(repeat, linepattern)"); glEnable(GL_LINE_STIPPLE); - checkGLcall("glEnable(GL_LINE_STIPPLE);\n"); + checkGLcall("glEnable(GL_LINE_STIPPLE);"); } else { glDisable(GL_LINE_STIPPLE); - checkGLcall("glDisable(GL_LINE_STIPPLE);\n"); + checkGLcall("glDisable(GL_LINE_STIPPLE);"); } } break; @@ -2560,13 +2573,13 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3 case D3DRS_POINTSIZE : TRACE("Set point size to %f\n", *((float*)&Value)); glPointSize(*((float*)&Value)); - checkGLcall("glPointSize(...);\n"); + checkGLcall("glPointSize(...);"); break; case D3DRS_POINTSIZE_MIN : if (GL_SUPPORT(EXT_POINT_PARAMETERS)) { GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, *((float*)&Value)); - checkGLcall("glPointParameterfEXT(...);\n"); + checkGLcall("glPointParameterfEXT(...);"); } else { FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n"); } @@ -2575,7 +2588,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3 case D3DRS_POINTSIZE_MAX : if (GL_SUPPORT(EXT_POINT_PARAMETERS)) { GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, *((float*)&Value)); - checkGLcall("glPointParameterfEXT(...);\n"); + checkGLcall("glPointParameterfEXT(...);"); } else { FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n"); } @@ -2595,7 +2608,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) { GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att); - checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);\n"); + checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);"); } else { TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n"); } @@ -2603,7 +2616,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3 GLfloat att[3] = {1.0f, 0.0f, 0.0f}; if (GL_SUPPORT(EXT_POINT_PARAMETERS)) { GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att); - checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);\n"); + checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);"); } else { TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n"); } @@ -2621,7 +2634,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3 Value & D3DCOLORWRITEENABLE_GREEN, Value & D3DCOLORWRITEENABLE_BLUE, Value & D3DCOLORWRITEENABLE_ALPHA); - checkGLcall("glColorMask(...)\n"); + checkGLcall("glColorMask(...)"); break; /* Unhandled yet...! */ @@ -2853,7 +2866,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 ifa /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */ - TRACE("(%p) : stub, Stage=%ld, Type=%d, Value=%ld\n", This, Stage, Type, Value); + TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value); /* Reject invalid texture units */ if (Stage >= GL_LIMITS(textures)) { diff --git a/dlls/d3d8/surface.c b/dlls/d3d8/surface.c index ce36511d660eab6f26ca5c88850ce89b7bbf5bcb..2f01777eae0483586e6c5079d5ecc5dab87be400 100644 --- a/dlls/d3d8/surface.c +++ b/dlls/d3d8/surface.c @@ -193,13 +193,15 @@ HRESULT WINAPI IDirect3DSurface8Impl_LockRect(LPDIRECT3DSURFACE8 iface, D3DLOCKE { long j; + GLenum format = D3DFmt2GLFmt(This->Device, This->myDesc.Format); + GLenum type = D3DFmt2GLType(This->Device, This->myDesc.Format); for (j = This->lockedRect.top; j < This->lockedRect.bottom - This->lockedRect.top; ++j) { glReadPixels(This->lockedRect.left, This->lockedRect.bottom - j - 1, This->lockedRect.right - This->lockedRect.left, 1, - D3DFmt2GLFmt(This->Device, This->myDesc.Format), - D3DFmt2GLType(This->Device, This->myDesc.Format), + format, + type, (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top))); vcheckGLcall("glReadPixels"); } diff --git a/dlls/d3d8/utils.c b/dlls/d3d8/utils.c index a14ea509e4a76345ad09eb270d38ac2944d6d168..6aaa7093c6c3a8f3891a28bb5e38d645b048685e 100644 --- a/dlls/d3d8/utils.c +++ b/dlls/d3d8/utils.c @@ -165,6 +165,133 @@ const char* debug_d3dpool(D3DPOOL Pool) { } } +const char* debug_d3drenderstate(DWORD state) { + switch (state) { +#define D3DSTATE_TO_STR(u) case u: return #u + D3DSTATE_TO_STR(D3DRS_ZENABLE ); + D3DSTATE_TO_STR(D3DRS_FILLMODE ); + D3DSTATE_TO_STR(D3DRS_SHADEMODE ); + D3DSTATE_TO_STR(D3DRS_LINEPATTERN ); + D3DSTATE_TO_STR(D3DRS_ZWRITEENABLE ); + D3DSTATE_TO_STR(D3DRS_ALPHATESTENABLE ); + D3DSTATE_TO_STR(D3DRS_LASTPIXEL ); + D3DSTATE_TO_STR(D3DRS_SRCBLEND ); + D3DSTATE_TO_STR(D3DRS_DESTBLEND ); + D3DSTATE_TO_STR(D3DRS_CULLMODE ); + D3DSTATE_TO_STR(D3DRS_ZFUNC ); + D3DSTATE_TO_STR(D3DRS_ALPHAREF ); + D3DSTATE_TO_STR(D3DRS_ALPHAFUNC ); + D3DSTATE_TO_STR(D3DRS_DITHERENABLE ); + D3DSTATE_TO_STR(D3DRS_ALPHABLENDENABLE ); + D3DSTATE_TO_STR(D3DRS_FOGENABLE ); + D3DSTATE_TO_STR(D3DRS_SPECULARENABLE ); + D3DSTATE_TO_STR(D3DRS_ZVISIBLE ); + D3DSTATE_TO_STR(D3DRS_FOGCOLOR ); + D3DSTATE_TO_STR(D3DRS_FOGTABLEMODE ); + D3DSTATE_TO_STR(D3DRS_FOGSTART ); + D3DSTATE_TO_STR(D3DRS_FOGEND ); + D3DSTATE_TO_STR(D3DRS_FOGDENSITY ); + D3DSTATE_TO_STR(D3DRS_EDGEANTIALIAS ); + D3DSTATE_TO_STR(D3DRS_ZBIAS ); + D3DSTATE_TO_STR(D3DRS_RANGEFOGENABLE ); + D3DSTATE_TO_STR(D3DRS_STENCILENABLE ); + D3DSTATE_TO_STR(D3DRS_STENCILFAIL ); + D3DSTATE_TO_STR(D3DRS_STENCILZFAIL ); + D3DSTATE_TO_STR(D3DRS_STENCILPASS ); + D3DSTATE_TO_STR(D3DRS_STENCILFUNC ); + D3DSTATE_TO_STR(D3DRS_STENCILREF ); + D3DSTATE_TO_STR(D3DRS_STENCILMASK ); + D3DSTATE_TO_STR(D3DRS_STENCILWRITEMASK ); + D3DSTATE_TO_STR(D3DRS_TEXTUREFACTOR ); + D3DSTATE_TO_STR(D3DRS_WRAP0 ); + D3DSTATE_TO_STR(D3DRS_WRAP1 ); + D3DSTATE_TO_STR(D3DRS_WRAP2 ); + D3DSTATE_TO_STR(D3DRS_WRAP3 ); + D3DSTATE_TO_STR(D3DRS_WRAP4 ); + D3DSTATE_TO_STR(D3DRS_WRAP5 ); + D3DSTATE_TO_STR(D3DRS_WRAP6 ); + D3DSTATE_TO_STR(D3DRS_WRAP7 ); + D3DSTATE_TO_STR(D3DRS_CLIPPING ); + D3DSTATE_TO_STR(D3DRS_LIGHTING ); + D3DSTATE_TO_STR(D3DRS_AMBIENT ); + D3DSTATE_TO_STR(D3DRS_FOGVERTEXMODE ); + D3DSTATE_TO_STR(D3DRS_COLORVERTEX ); + D3DSTATE_TO_STR(D3DRS_LOCALVIEWER ); + D3DSTATE_TO_STR(D3DRS_NORMALIZENORMALS ); + D3DSTATE_TO_STR(D3DRS_DIFFUSEMATERIALSOURCE ); + D3DSTATE_TO_STR(D3DRS_SPECULARMATERIALSOURCE ); + D3DSTATE_TO_STR(D3DRS_AMBIENTMATERIALSOURCE ); + D3DSTATE_TO_STR(D3DRS_EMISSIVEMATERIALSOURCE ); + D3DSTATE_TO_STR(D3DRS_VERTEXBLEND ); + D3DSTATE_TO_STR(D3DRS_CLIPPLANEENABLE ); + D3DSTATE_TO_STR(D3DRS_SOFTWAREVERTEXPROCESSING ); + D3DSTATE_TO_STR(D3DRS_POINTSIZE ); + D3DSTATE_TO_STR(D3DRS_POINTSIZE_MIN ); + D3DSTATE_TO_STR(D3DRS_POINTSPRITEENABLE ); + D3DSTATE_TO_STR(D3DRS_POINTSCALEENABLE ); + D3DSTATE_TO_STR(D3DRS_POINTSCALE_A ); + D3DSTATE_TO_STR(D3DRS_POINTSCALE_B ); + D3DSTATE_TO_STR(D3DRS_POINTSCALE_C ); + D3DSTATE_TO_STR(D3DRS_MULTISAMPLEANTIALIAS ); + D3DSTATE_TO_STR(D3DRS_MULTISAMPLEMASK ); + D3DSTATE_TO_STR(D3DRS_PATCHEDGESTYLE ); + D3DSTATE_TO_STR(D3DRS_PATCHSEGMENTS ); + D3DSTATE_TO_STR(D3DRS_DEBUGMONITORTOKEN ); + D3DSTATE_TO_STR(D3DRS_POINTSIZE_MAX ); + D3DSTATE_TO_STR(D3DRS_INDEXEDVERTEXBLENDENABLE ); + D3DSTATE_TO_STR(D3DRS_COLORWRITEENABLE ); + D3DSTATE_TO_STR(D3DRS_TWEENFACTOR ); + D3DSTATE_TO_STR(D3DRS_BLENDOP ); + D3DSTATE_TO_STR(D3DRS_POSITIONORDER ); + D3DSTATE_TO_STR(D3DRS_NORMALORDER ); +#undef D3DSTATE_TO_STR + default: + FIXME("Unrecognized %lu render state!\n", state); + return "unrecognized"; + } +} + +const char* debug_d3dtexturestate(DWORD state) { + switch (state) { +#define D3DSTATE_TO_STR(u) case u: return #u + D3DSTATE_TO_STR(D3DTSS_COLOROP ); + D3DSTATE_TO_STR(D3DTSS_COLORARG1 ); + D3DSTATE_TO_STR(D3DTSS_COLORARG2 ); + D3DSTATE_TO_STR(D3DTSS_ALPHAOP ); + D3DSTATE_TO_STR(D3DTSS_ALPHAARG1 ); + D3DSTATE_TO_STR(D3DTSS_ALPHAARG2 ); + D3DSTATE_TO_STR(D3DTSS_BUMPENVMAT00 ); + D3DSTATE_TO_STR(D3DTSS_BUMPENVMAT01 ); + D3DSTATE_TO_STR(D3DTSS_BUMPENVMAT10 ); + D3DSTATE_TO_STR(D3DTSS_BUMPENVMAT11 ); + D3DSTATE_TO_STR(D3DTSS_TEXCOORDINDEX ); + D3DSTATE_TO_STR(D3DTSS_ADDRESSU ); + D3DSTATE_TO_STR(D3DTSS_ADDRESSV ); + D3DSTATE_TO_STR(D3DTSS_BORDERCOLOR ); + D3DSTATE_TO_STR(D3DTSS_MAGFILTER ); + D3DSTATE_TO_STR(D3DTSS_MINFILTER ); + D3DSTATE_TO_STR(D3DTSS_MIPFILTER ); + D3DSTATE_TO_STR(D3DTSS_MIPMAPLODBIAS ); + D3DSTATE_TO_STR(D3DTSS_MAXMIPLEVEL ); + D3DSTATE_TO_STR(D3DTSS_MAXANISOTROPY ); + D3DSTATE_TO_STR(D3DTSS_BUMPENVLSCALE ); + D3DSTATE_TO_STR(D3DTSS_BUMPENVLOFFSET ); + D3DSTATE_TO_STR(D3DTSS_TEXTURETRANSFORMFLAGS ); + D3DSTATE_TO_STR(D3DTSS_ADDRESSW ); + D3DSTATE_TO_STR(D3DTSS_COLORARG0 ); + D3DSTATE_TO_STR(D3DTSS_ALPHAARG0 ); + D3DSTATE_TO_STR(D3DTSS_RESULTARG ); +#undef D3DSTATE_TO_STR + case 12: + /* Note D3DTSS are not consecutive, so skip these */ + return "unused"; + break; + default: + FIXME("Unrecognized %lu texture state!\n", state); + return "unrecognized"; + } +} + /* * Simple utility routines used for dx -> gl mapping of byte formats */ @@ -564,6 +691,17 @@ void set_tex_op(LPDIRECT3DDEVICE8 iface, BOOL isAlpha, int Stage, D3DTEXTUREOP o TRACE("Alpha?(%d), Stage:%d Op(%d), a1(%ld), a2(%ld), a3(%ld)\n", isAlpha, Stage, op, arg1, arg2, arg3); if (op == D3DTOP_DISABLE) return; + /* Note: Operations usually involve two ars, src0 and src1 and are operations of + the form (a1 <operation> a2). However, some of the more complex operations + take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added + in a third parameter called a0. Therefore these are operations of the form + a0 <operation> a1 <operation> a2, ie the new parameter goes to the front. + + However, below we treat the new (a0) parameter as src2/opr2, so in the actual + functions below, expect their syntax to differ slightly to those listed in the + manuals, ie replace arg1 with arg3, arg2 with arg1 and arg3 with arg2 + This affects D3DTOP_MULTIPLYADD and D3DTOP_LERP */ + if (isAlpha) { comb_target = useext(GL_COMBINE_ALPHA); src0_target = useext(GL_SOURCE0_ALPHA); @@ -589,7 +727,7 @@ void set_tex_op(LPDIRECT3DDEVICE8 iface, BOOL isAlpha, int Stage, D3DTEXTUREOP o The default argument is D3DTA_TEXTURE. If no texture is set for this stage, then the default argument is D3DTA_DIFFUSE. FIXME? If texture added/removed, may need to reset back as well? */ - if (isAlpha && Stage==0 && This->StateBlock->textures[Stage] == NULL && arg1 == D3DTA_TEXTURE) { + if (isAlpha && This->StateBlock->textures[Stage] == NULL && arg1 == D3DTA_TEXTURE) { GetSrcAndOpFromValue(D3DTA_DIFFUSE, isAlpha, &src1, &opr1); } else { GetSrcAndOpFromValue(arg1, isAlpha, &src1, &opr1); @@ -817,17 +955,17 @@ void set_tex_op(LPDIRECT3DDEVICE8 iface, BOOL isAlpha, int Stage, D3DTEXTUREOP o case D3DTOP_LERP: glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)); checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src2); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); checkGLcall("GL_TEXTURE_ENV, src0_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src1_target, src3); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); checkGLcall("GL_TEXTURE_ENV, src1_target, src3"); - glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src1); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src3); checkGLcall("GL_TEXTURE_ENV, src2_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, src1); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, src3); checkGLcall("GL_TEXTURE_ENV, opr2_target, src1"); glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); @@ -835,43 +973,95 @@ void set_tex_op(LPDIRECT3DDEVICE8 iface, BOOL isAlpha, int Stage, D3DTEXTUREOP o default: Handled = FALSE; } + if (Handled) { + BOOL combineOK = TRUE; #if defined(GL_NV_texture_env_combine4) + DWORD op2; + + if (isAlpha) { + op2 = This->UpdateStateBlock->texture_state[Stage][D3DTSS_COLOROP]; + } else { + op2 = This->UpdateStateBlock->texture_state[Stage][D3DTSS_ALPHAOP]; + } + /* Note: If COMBINE4 in effect cant go back to combine! */ - if (isAlpha) { - switch (This->UpdateStateBlock->texture_state[Stage][D3DTSS_COLOROP]) - { - case D3DTOP_ADDSMOOTH: - case D3DTOP_BLENDTEXTUREALPHAPM: - case D3DTOP_MODULATEALPHA_ADDCOLOR: - case D3DTOP_MODULATECOLOR_ADDALPHA: - case D3DTOP_MODULATEINVALPHA_ADDCOLOR: - case D3DTOP_MODULATEINVCOLOR_ADDALPHA: - case D3DTOP_MULTIPLYADD: - FIXME("Cant have COMBINE4 and COMBINE in efferct together, alphaop=%d\n", op); + switch (op2) + { + case D3DTOP_ADDSMOOTH: + case D3DTOP_BLENDTEXTUREALPHAPM: + case D3DTOP_MODULATEALPHA_ADDCOLOR: + case D3DTOP_MODULATECOLOR_ADDALPHA: + case D3DTOP_MODULATEINVALPHA_ADDCOLOR: + case D3DTOP_MODULATEINVCOLOR_ADDALPHA: + case D3DTOP_MULTIPLYADD: + /* Ignore those implemented in both cases */ + switch (op) { + case D3DTOP_SELECTARG1: + case D3DTOP_SELECTARG2: + combineOK = FALSE; + Handled = FALSE; + break; + default: + FIXME("Cant have COMBINE4 and COMBINE in efferct together, thisop=%d, otherop=%ld, isAlpha(%d)\n", + op, op2, isAlpha); return; } } #endif - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)); - checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)"); - return; + + if (combineOK == TRUE) { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)); + checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)"); + return; + } } /* Other texture operations require special extensions: */ #if defined(GL_NV_texture_env_combine4) if (isAlpha) { + opr = GL_SRC_ALPHA; invopr = GL_ONE_MINUS_SRC_ALPHA; src3_target = GL_SOURCE3_ALPHA_NV; opr3_target = GL_OPERAND3_ALPHA_NV; } else { + opr = GL_SRC_COLOR; invopr = GL_ONE_MINUS_SRC_COLOR; src3_target = GL_SOURCE3_RGB_NV; opr3_target = GL_OPERAND3_RGB_NV; } Handled = TRUE; /* Again, assume handled */ switch (op) { + case D3DTOP_SELECTARG1: /* = a1 * 1 + 0 * 0 */ + case D3DTOP_SELECTARG2: /* = a2 * 1 + 0 * 0 */ + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + if (op == D3DTOP_SELECTARG1) { + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + } else { + glTexEnvi(GL_TEXTURE_ENV, src0_target, src2); + checkGLcall("GL_TEXTURE_ENV, src0_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2"); + } + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr"); + break; + case D3DTOP_ADDSMOOTH: glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); @@ -1037,21 +1227,21 @@ void set_tex_op(LPDIRECT3DDEVICE8 iface, BOOL isAlpha, int Stage, D3DTEXTUREOP o case D3DTOP_MULTIPLYADD: glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); - glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src3); checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); - glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3); checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); - glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src1); checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); - glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1); checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); - glTexEnvi(GL_TEXTURE_ENV, src3_target, src3); + glTexEnvi(GL_TEXTURE_ENV, src3_target, src2); checkGLcall("GL_TEXTURE_ENV, src3_target, src3"); - glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr3); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2); checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3"); glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); checkGLcall("GL_TEXTURE_ENV, scal_target, 1");