Add {G,S}etRenderState and {G,S}etTextureStageState support, and
ensure the stateblock is fully populated at device startup.
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index 9e4b808..186609c 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -374,15 +374,12 @@
HRESULT WINAPI IDirect3DDevice9Impl_SetRenderState(LPDIRECT3DDEVICE9 iface, D3DRENDERSTATETYPE State, DWORD Value) {
IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
- FIXME("(%p) : stub\n", This);
- return D3D_OK;
+ return IWineD3DDevice_SetRenderState(This->WineD3DDevice, State, Value);
}
HRESULT WINAPI IDirect3DDevice9Impl_GetRenderState(LPDIRECT3DDEVICE9 iface, D3DRENDERSTATETYPE State, DWORD* pValue) {
IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
- TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
- *pValue = This->StateBlock->renderstate[State];
- return D3D_OK;
+ return IWineD3DDevice_GetRenderState(This->WineD3DDevice, State, pValue);
}
HRESULT WINAPI IDirect3DDevice9Impl_SetClipStatus(LPDIRECT3DDEVICE9 iface, CONST D3DCLIPSTATUS9* pClipStatus) {
@@ -411,15 +408,12 @@
HRESULT WINAPI IDirect3DDevice9Impl_GetTextureStageState(LPDIRECT3DDEVICE9 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
- TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
- *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
- return D3D_OK;
+ return IWineD3DDevice_GetTextureStageState(This->WineD3DDevice, Stage, Type, pValue);
}
HRESULT WINAPI IDirect3DDevice9Impl_SetTextureStageState(LPDIRECT3DDEVICE9 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
- FIXME("(%p) : stub\n", This);
- return D3D_OK;
+ return IWineD3DDevice_SetTextureStageState(This->WineD3DDevice, Stage, Type, Value);
}
HRESULT WINAPI IDirect3DDevice9Impl_GetSamplerState(LPDIRECT3DDEVICE9 iface, DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD* pValue) {
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 1ddc657..4524ae3 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -124,6 +124,79 @@
glPopMatrix();
}
+/* Apply the current values to the specified texture stage */
+void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Stage, DWORD Flags) {
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+ int i = 0;
+ float col[4];
+ BOOL changeTexture = TRUE;
+
+ TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
+ for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
+
+ BOOL skip = FALSE;
+
+ switch (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 */
+ 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 */
+ skip = TRUE;
+ break;
+
+ /* Performance: If the texture states only impact settings for the texture unit
+ (compared to the texture object) then there is no need to reapply them. The
+ only time they need applying is the first time, since we cheat and put the
+ values into the stateblock without applying.
+ Per-texture unit: texture function (eg. combine), ops and args
+ texture env color
+ texture generation settings
+ Note: Due to some special conditions there may be a need to do particular ones
+ of these, which is what the Flags allows */
+ case D3DTSS_COLOROP:
+ case D3DTSS_TEXCOORDINDEX:
+ if (!(Flags == REAPPLY_ALL)) skip=TRUE;
+ break;
+
+ case D3DTSS_ALPHAOP:
+ if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
+ break;
+
+ default:
+ skip = FALSE;
+ }
+
+ if (skip == FALSE) {
+ /* Performance: Only change to this texture if we have to */
+ if (changeTexture) {
+ /* Make appropriate texture active */
+ if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+ GL_ACTIVETEXTURE(Stage);
+ } else if (Stage > 0) {
+ FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
+ }
+ changeTexture = FALSE;
+ }
+
+ /* Now apply the change */
+ IWineD3DDevice_SetTextureStageState(iface, Stage, i, This->stateBlock->textureState[Stage][i]);
+ }
+ }
+
+ /* Note the D3DRS value applies to all textures, but GL has one
+ * per texture, so apply it now ready to be used!
+ */
+ D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[D3DRS_TEXTUREFACTOR], col);
+ glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
+ checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
+
+ TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
+}
+
/**********************************************************
* IWineD3DDevice implementation follows
**********************************************************/
@@ -347,7 +420,7 @@
GL_ACTIVETEXTURE(tex);
#if 0 /* TODO: */
set_texture_matrix((float *)lpmatrix,
- This->updateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
+ This->updateStateBlock->textureState[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
#endif
}
@@ -992,13 +1065,10 @@
checkGLcall("glMaterialfv");
/* Only change material color if specular is enabled, otherwise it is set to black */
-#if 0 /* TODO */
- if (This->stateBlock->renderstate[D3DRS_SPECULARENABLE]) {
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
+ if (This->stateBlock->renderState[D3DRS_SPECULARENABLE]) {
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
checkGLcall("glMaterialfv");
} else {
-#endif
- {
float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
checkGLcall("glMaterialfv");
@@ -1108,6 +1178,1418 @@
}
/*****
+ * Get / Set Render States
+ * TODO: Verify against dx9 definitions
+ *****/
+HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
+
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+ DWORD OldValue = This->stateBlock->renderState[State];
+
+ /* Simple way of refering to either a DWORD or a 4 byte float */
+ union {
+ DWORD d;
+ float f;
+ } tmpvalue;
+
+ 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;
+
+ /* Handle recording of state blocks */
+ if (This->isRecordingState) {
+ TRACE("Recording... not performing anything\n");
+ return D3D_OK;
+ }
+
+ ENTER_GL();
+
+ switch (State) {
+ case D3DRS_FILLMODE :
+ switch ((D3DFILLMODE) Value) {
+ case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
+ case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
+ case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
+ default:
+ FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
+ }
+ checkGLcall("glPolygonMode (fillmode)");
+ break;
+
+ case D3DRS_LIGHTING :
+ if (Value) {
+ glEnable(GL_LIGHTING);
+ checkGLcall("glEnable GL_LIGHTING");
+ } else {
+ glDisable(GL_LIGHTING);
+ checkGLcall("glDisable GL_LIGHTING");
+ }
+ break;
+
+ case D3DRS_ZENABLE :
+ switch ((D3DZBUFFERTYPE) Value) {
+ case D3DZB_FALSE:
+ glDisable(GL_DEPTH_TEST);
+ checkGLcall("glDisable GL_DEPTH_TEST");
+ break;
+ case D3DZB_TRUE:
+ glEnable(GL_DEPTH_TEST);
+ checkGLcall("glEnable GL_DEPTH_TEST");
+ break;
+ case D3DZB_USEW:
+ glEnable(GL_DEPTH_TEST);
+ checkGLcall("glEnable GL_DEPTH_TEST");
+ FIXME("W buffer is not well handled\n");
+ break;
+ default:
+ FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
+ }
+ break;
+
+ case D3DRS_CULLMODE :
+
+ /* If we are culling "back faces with clockwise vertices" then
+ set front faces to be counter clockwise and enable culling
+ of back faces */
+ switch ((D3DCULL) Value) {
+ case D3DCULL_NONE:
+ glDisable(GL_CULL_FACE);
+ checkGLcall("glDisable GL_CULL_FACE");
+ break;
+ case D3DCULL_CW:
+ glEnable(GL_CULL_FACE);
+ checkGLcall("glEnable GL_CULL_FACE");
+ if (This->renderUpsideDown) {
+ glFrontFace(GL_CW);
+ checkGLcall("glFrontFace GL_CW");
+ } else {
+ glFrontFace(GL_CCW);
+ checkGLcall("glFrontFace GL_CCW");
+ }
+ glCullFace(GL_BACK);
+ break;
+ case D3DCULL_CCW:
+ glEnable(GL_CULL_FACE);
+ checkGLcall("glEnable GL_CULL_FACE");
+ if (This->renderUpsideDown) {
+ glFrontFace(GL_CCW);
+ checkGLcall("glFrontFace GL_CCW");
+ } else {
+ glFrontFace(GL_CW);
+ checkGLcall("glFrontFace GL_CW");
+ }
+ glCullFace(GL_BACK);
+ break;
+ default:
+ FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
+ }
+ break;
+
+ case D3DRS_SHADEMODE :
+ switch ((D3DSHADEMODE) Value) {
+ case D3DSHADE_FLAT:
+ glShadeModel(GL_FLAT);
+ checkGLcall("glShadeModel");
+ break;
+ case D3DSHADE_GOURAUD:
+ glShadeModel(GL_SMOOTH);
+ checkGLcall("glShadeModel");
+ break;
+ case D3DSHADE_PHONG:
+ FIXME("D3DSHADE_PHONG isn't supported?\n");
+
+ LEAVE_GL();
+ return D3DERR_INVALIDCALL;
+ default:
+ FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
+ }
+ break;
+
+ case D3DRS_DITHERENABLE :
+ if (Value) {
+ glEnable(GL_DITHER);
+ checkGLcall("glEnable GL_DITHER");
+ } else {
+ glDisable(GL_DITHER);
+ checkGLcall("glDisable GL_DITHER");
+ }
+ break;
+
+ case D3DRS_ZWRITEENABLE :
+ if (Value) {
+ glDepthMask(1);
+ checkGLcall("glDepthMask");
+ } else {
+ glDepthMask(0);
+ checkGLcall("glDepthMask");
+ }
+ break;
+
+ case D3DRS_ZFUNC :
+ {
+ int glParm = GL_LESS;
+
+ switch ((D3DCMPFUNC) Value) {
+ case D3DCMP_NEVER: glParm=GL_NEVER; break;
+ case D3DCMP_LESS: glParm=GL_LESS; break;
+ case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
+ case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
+ case D3DCMP_GREATER: glParm=GL_GREATER; break;
+ case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
+ case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
+ case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
+ default:
+ FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
+ }
+ glDepthFunc(glParm);
+ checkGLcall("glDepthFunc");
+ }
+ break;
+
+ case D3DRS_AMBIENT :
+ {
+ float col[4];
+ D3DCOLORTOGLFLOAT4(Value, col);
+ TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
+ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
+ checkGLcall("glLightModel for MODEL_AMBIENT");
+
+ }
+ break;
+
+ case D3DRS_ALPHABLENDENABLE :
+ if (Value) {
+ glEnable(GL_BLEND);
+ checkGLcall("glEnable GL_BLEND");
+ } else {
+ glDisable(GL_BLEND);
+ checkGLcall("glDisable GL_BLEND");
+ };
+ break;
+
+ case D3DRS_SRCBLEND :
+ case D3DRS_DESTBLEND :
+ {
+ int newVal = GL_ZERO;
+ switch (Value) {
+ case D3DBLEND_ZERO : newVal = GL_ZERO; break;
+ case D3DBLEND_ONE : newVal = GL_ONE; break;
+ case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
+ case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
+ case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
+ case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
+ case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
+ case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
+ case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
+ case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
+ case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
+
+ case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
+ This->srcBlend = newVal;
+ This->dstBlend = newVal;
+ break;
+
+ case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
+ This->srcBlend = newVal;
+ This->dstBlend = newVal;
+ break;
+ default:
+ FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
+ }
+
+ if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
+ if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
+ TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
+ glBlendFunc(This->srcBlend, This->dstBlend);
+
+ checkGLcall("glBlendFunc");
+ }
+ break;
+
+ case D3DRS_ALPHATESTENABLE :
+ if (Value) {
+ glEnable(GL_ALPHA_TEST);
+ checkGLcall("glEnable GL_ALPHA_TEST");
+ } else {
+ glDisable(GL_ALPHA_TEST);
+ checkGLcall("glDisable GL_ALPHA_TEST");
+ }
+ break;
+
+ case D3DRS_ALPHAFUNC :
+ {
+ int glParm = GL_LESS;
+ float ref = ((float) This->stateBlock->renderState[D3DRS_ALPHAREF]) / 255.0f;
+
+ switch ((D3DCMPFUNC) Value) {
+ case D3DCMP_NEVER: glParm = GL_NEVER; break;
+ case D3DCMP_LESS: glParm = GL_LESS; break;
+ case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
+ case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
+ case D3DCMP_GREATER: glParm = GL_GREATER; break;
+ case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
+ case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
+ case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
+ default:
+ FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
+ }
+ TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
+ glAlphaFunc(glParm, ref);
+ This->alphafunc = glParm;
+ checkGLcall("glAlphaFunc");
+ }
+ break;
+
+ case D3DRS_ALPHAREF :
+ {
+ int glParm = This->alphafunc;
+ float ref = 1.0f;
+
+ ref = ((float) Value) / 255.0f;
+ TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
+ glAlphaFunc(glParm, ref);
+ checkGLcall("glAlphaFunc");
+ }
+ break;
+
+ case D3DRS_CLIPPLANEENABLE :
+ case D3DRS_CLIPPING :
+ {
+ /* Ensure we only do the changed clip planes */
+ DWORD enable = 0xFFFFFFFF;
+ DWORD disable = 0x00000000;
+
+ /* If enabling / disabling all */
+ if (State == D3DRS_CLIPPING) {
+ if (Value) {
+ enable = This->stateBlock->renderState[D3DRS_CLIPPLANEENABLE];
+ disable = 0x00;
+ } else {
+ disable = This->stateBlock->renderState[D3DRS_CLIPPLANEENABLE];
+ enable = 0x00;
+ }
+ } else {
+ enable = Value & ~OldValue;
+ disable = ~Value & OldValue;
+ }
+
+ if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
+ if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
+ if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
+ if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
+ if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
+ if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
+
+ if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
+ if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
+ if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
+ if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
+ if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
+ if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
+
+ /** update clipping status */
+ if (enable) {
+ This->stateBlock->clip_status.ClipUnion = 0;
+ This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
+ } else {
+ This->stateBlock->clip_status.ClipUnion = 0;
+ This->stateBlock->clip_status.ClipIntersection = 0;
+ }
+ }
+ break;
+
+ case D3DRS_BLENDOP :
+ {
+ int glParm = GL_FUNC_ADD;
+
+ switch ((D3DBLENDOP) Value) {
+ case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
+ case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
+ case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
+ case D3DBLENDOP_MIN : glParm = GL_MIN; break;
+ case D3DBLENDOP_MAX : glParm = GL_MAX; break;
+ default:
+ FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
+ }
+ TRACE("glBlendEquation(%x)\n", glParm);
+ glBlendEquation(glParm);
+ checkGLcall("glBlendEquation");
+ }
+ break;
+
+ case D3DRS_TEXTUREFACTOR :
+ {
+ unsigned int i;
+
+ /* Note the texture color applies to all textures whereas
+ GL_TEXTURE_ENV_COLOR applies to active only */
+ float col[4];
+ D3DCOLORTOGLFLOAT4(Value, col);
+ /* Set the default alpha blend color */
+ glBlendColor(col[0], col[1], col[2], col[3]);
+ checkGLcall("glBlendColor");
+
+ /* And now the default texture color as well */
+ for (i = 0; i < GL_LIMITS(textures); i++) {
+
+ /* Note the D3DRS value applies to all textures, but GL has one
+ per texture, so apply it now ready to be used! */
+ if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+ GL_ACTIVETEXTURE(i);
+ } else if (i>0) {
+ FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
+ }
+
+ glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
+ checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
+ }
+ }
+ break;
+
+ case D3DRS_SPECULARENABLE :
+ {
+ /* 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 (Value) {
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
+ checkGLcall("glMaterialfv");
+ 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)");
+ } 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)");
+ }
+ }
+ break;
+
+ case D3DRS_STENCILENABLE :
+ if (Value) {
+ glEnable(GL_STENCIL_TEST);
+ checkGLcall("glEnable GL_STENCIL_TEST");
+ } else {
+ glDisable(GL_STENCIL_TEST);
+ checkGLcall("glDisable GL_STENCIL_TEST");
+ }
+ break;
+
+ case D3DRS_STENCILFUNC :
+ {
+ int glParm = GL_ALWAYS;
+ int ref = This->stateBlock->renderState[D3DRS_STENCILREF];
+ GLuint mask = This->stateBlock->renderState[D3DRS_STENCILMASK];
+
+ switch ((D3DCMPFUNC) Value) {
+ case D3DCMP_NEVER: glParm=GL_NEVER; break;
+ case D3DCMP_LESS: glParm=GL_LESS; break;
+ case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
+ case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
+ case D3DCMP_GREATER: glParm=GL_GREATER; break;
+ case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
+ case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
+ case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
+ default:
+ FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
+ }
+ TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
+ This->stencilfunc = glParm;
+ glStencilFunc(glParm, ref, mask);
+ checkGLcall("glStencilFunc");
+ }
+ break;
+
+ case D3DRS_STENCILREF :
+ {
+ int glParm = This->stencilfunc;
+ int ref = 0;
+ GLuint mask = This->stateBlock->renderState[D3DRS_STENCILMASK];
+
+ ref = Value;
+ TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
+ glStencilFunc(glParm, ref, mask);
+ checkGLcall("glStencilFunc");
+ }
+ break;
+
+ case D3DRS_STENCILMASK :
+ {
+ int glParm = This->stencilfunc;
+ int ref = This->stateBlock->renderState[D3DRS_STENCILREF];
+ GLuint mask = Value;
+
+ TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
+ glStencilFunc(glParm, ref, mask);
+ checkGLcall("glStencilFunc");
+ }
+ break;
+
+ case D3DRS_STENCILFAIL :
+ {
+ GLenum fail ;
+ GLenum zpass ;
+ GLenum zfail ;
+
+ fail = StencilOp(Value);
+ glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
+ checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
+ glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
+ checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
+
+ TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
+ glStencilOp(fail, zfail, zpass);
+ checkGLcall("glStencilOp(fail, zfail, zpass);");
+ }
+ break;
+ case D3DRS_STENCILZFAIL :
+ {
+ GLenum fail ;
+ GLenum zpass ;
+ GLenum zfail ;
+
+ glGetIntegerv(GL_STENCIL_FAIL, &fail);
+ checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
+ glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
+ checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
+ zfail = StencilOp(Value);
+
+ TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
+ glStencilOp(fail, zfail, zpass);
+ checkGLcall("glStencilOp(fail, zfail, zpass);");
+ }
+ break;
+ case D3DRS_STENCILPASS :
+ {
+ GLenum fail ;
+ GLenum zpass ;
+ GLenum zfail ;
+
+ glGetIntegerv(GL_STENCIL_FAIL, &fail);
+ checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
+ zpass = StencilOp(Value);
+ glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
+ checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
+
+ TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
+ glStencilOp(fail, zfail, zpass);
+ checkGLcall("glStencilOp(fail, zfail, zpass);");
+ }
+ break;
+
+ case D3DRS_STENCILWRITEMASK :
+ {
+ glStencilMask(Value);
+ TRACE("glStencilMask(%lu)\n", Value);
+ checkGLcall("glStencilMask");
+ }
+ break;
+
+ case D3DRS_FOGENABLE :
+ {
+ if (Value/* && This->stateBlock->renderState[D3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
+ glEnable(GL_FOG);
+ checkGLcall("glEnable GL_FOG");
+ } else {
+ glDisable(GL_FOG);
+ checkGLcall("glDisable GL_FOG");
+ }
+ }
+ break;
+
+ case D3DRS_RANGEFOGENABLE :
+ {
+ if (Value) {
+ TRACE("Enabled RANGEFOG");
+ } else {
+ TRACE("Disabled RANGEFOG");
+ }
+ }
+ break;
+
+ case D3DRS_FOGCOLOR :
+ {
+ float col[4];
+ D3DCOLORTOGLFLOAT4(Value, col);
+ /* Set the default alpha blend color */
+ glFogfv(GL_FOG_COLOR, &col[0]);
+ checkGLcall("glFog GL_FOG_COLOR");
+ }
+ break;
+
+ case D3DRS_FOGTABLEMODE :
+ {
+ glHint(GL_FOG_HINT, GL_NICEST);
+ switch (Value) {
+ case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
+ case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
+ case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
+ case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
+ default:
+ FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
+ }
+ if (GL_SUPPORT(NV_FOG_DISTANCE)) {
+ glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
+ }
+ }
+ break;
+
+ case D3DRS_FOGVERTEXMODE :
+ {
+ glHint(GL_FOG_HINT, GL_FASTEST);
+ switch (Value) {
+ case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
+ case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
+ case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
+ case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
+ default:
+ FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
+ }
+ if (GL_SUPPORT(NV_FOG_DISTANCE)) {
+ glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[D3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
+ }
+ }
+ break;
+
+ case D3DRS_FOGSTART :
+ {
+ tmpvalue.d = Value;
+ glFogfv(GL_FOG_START, &tmpvalue.f);
+ checkGLcall("glFogf(GL_FOG_START, (float) Value)");
+ TRACE("Fog Start == %f\n", tmpvalue.f);
+ }
+ break;
+
+ case D3DRS_FOGEND :
+ {
+ tmpvalue.d = Value;
+ glFogfv(GL_FOG_END, &tmpvalue.f);
+ checkGLcall("glFogf(GL_FOG_END, (float) Value)");
+ TRACE("Fog End == %f\n", tmpvalue.f);
+ }
+ break;
+
+ case D3DRS_FOGDENSITY :
+ {
+ tmpvalue.d = Value;
+ glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
+ checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
+ }
+ break;
+
+ case D3DRS_VERTEXBLEND :
+ {
+ This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
+ TRACE("Vertex Blending state to %ld\n", Value);
+ }
+ break;
+
+ case D3DRS_TWEENFACTOR :
+ {
+ tmpvalue.d = Value;
+ This->updateStateBlock->tween_factor = tmpvalue.f;
+ TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
+ }
+ break;
+
+ case D3DRS_INDEXEDVERTEXBLENDENABLE :
+ {
+ TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
+ }
+ break;
+
+ case D3DRS_COLORVERTEX :
+ case D3DRS_DIFFUSEMATERIALSOURCE :
+ case D3DRS_SPECULARMATERIALSOURCE :
+ case D3DRS_AMBIENTMATERIALSOURCE :
+ case D3DRS_EMISSIVEMATERIALSOURCE :
+ {
+ GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
+
+ if (This->stateBlock->renderState[D3DRS_COLORVERTEX]) {
+ TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
+ This->stateBlock->renderState[D3DRS_DIFFUSEMATERIALSOURCE],
+ This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE],
+ This->stateBlock->renderState[D3DRS_EMISSIVEMATERIALSOURCE],
+ This->stateBlock->renderState[D3DRS_SPECULARMATERIALSOURCE]);
+
+ if (This->stateBlock->renderState[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
+ if (This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
+ Parm = GL_AMBIENT_AND_DIFFUSE;
+ } else {
+ Parm = GL_DIFFUSE;
+ }
+ } else if (This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
+ Parm = GL_AMBIENT;
+ } else if (This->stateBlock->renderState[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
+ Parm = GL_EMISSION;
+ } else if (This->stateBlock->renderState[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
+ Parm = GL_SPECULAR;
+ } else {
+ Parm = -1;
+ }
+
+ if (Parm == -1) {
+ if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
+ } else {
+ This->tracking_color = NEEDS_TRACKING;
+ This->tracking_parm = Parm;
+ }
+
+ } else {
+ if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
+ }
+ }
+ break;
+
+ case D3DRS_LINEPATTERN :
+ {
+ union {
+ DWORD d;
+ D3DLINEPATTERN lp;
+ } tmppattern;
+ tmppattern.d = Value;
+
+ TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
+
+ if (tmppattern.lp.wRepeatFactor) {
+ glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
+ checkGLcall("glLineStipple(repeat, linepattern)");
+ glEnable(GL_LINE_STIPPLE);
+ checkGLcall("glEnable(GL_LINE_STIPPLE);");
+ } else {
+ glDisable(GL_LINE_STIPPLE);
+ checkGLcall("glDisable(GL_LINE_STIPPLE);");
+ }
+ }
+ break;
+
+ case D3DRS_ZBIAS :
+ {
+ if (Value) {
+ tmpvalue.d = Value;
+ TRACE("ZBias value %f\n", tmpvalue.f);
+ glPolygonOffset(0, -tmpvalue.f);
+ checkGLcall("glPolygonOffset(0, -Value)");
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
+ glEnable(GL_POLYGON_OFFSET_LINE);
+ checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
+ glEnable(GL_POLYGON_OFFSET_POINT);
+ checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
+ } else {
+ glDisable(GL_POLYGON_OFFSET_FILL);
+ checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
+ glDisable(GL_POLYGON_OFFSET_LINE);
+ checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
+ glDisable(GL_POLYGON_OFFSET_POINT);
+ checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
+ }
+ }
+ break;
+
+ case D3DRS_NORMALIZENORMALS :
+ if (Value) {
+ glEnable(GL_NORMALIZE);
+ checkGLcall("glEnable(GL_NORMALIZE);");
+ } else {
+ glDisable(GL_NORMALIZE);
+ checkGLcall("glDisable(GL_NORMALIZE);");
+ }
+ break;
+
+ case D3DRS_POINTSIZE :
+ tmpvalue.d = Value;
+ TRACE("Set point size to %f\n", tmpvalue.f);
+ glPointSize(tmpvalue.f);
+ checkGLcall("glPointSize(...);");
+ break;
+
+ case D3DRS_POINTSIZE_MIN :
+ if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
+ tmpvalue.d = Value;
+ GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
+ checkGLcall("glPointParameterfEXT(...);");
+ } else {
+ FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
+ }
+ break;
+
+ case D3DRS_POINTSIZE_MAX :
+ if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
+ tmpvalue.d = Value;
+ GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
+ checkGLcall("glPointParameterfEXT(...);");
+ } else {
+ FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
+ }
+ break;
+
+ case D3DRS_POINTSCALE_A :
+ case D3DRS_POINTSCALE_B :
+ case D3DRS_POINTSCALE_C :
+ case D3DRS_POINTSCALEENABLE :
+ {
+ /* If enabled, supply the parameters, otherwise fall back to defaults */
+ if (This->stateBlock->renderState[D3DRS_POINTSCALEENABLE]) {
+ GLfloat att[3] = {1.0f, 0.0f, 0.0f};
+ att[0] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_A]);
+ att[1] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_B]);
+ att[2] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_C]);
+
+ if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
+ GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
+ checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
+ } else {
+ TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
+ }
+ } else {
+ 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, ...);");
+ } else {
+ TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
+ }
+ }
+ break;
+ }
+
+ case D3DRS_COLORWRITEENABLE :
+ {
+ TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
+ Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
+ Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
+ Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
+ Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
+ glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
+ Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
+ Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
+ Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
+ checkGLcall("glColorMask(...)");
+ }
+ break;
+
+ case D3DRS_LOCALVIEWER :
+ {
+ GLint state = (Value) ? 1 : 0;
+ TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
+ glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
+ }
+ break;
+
+ case D3DRS_LASTPIXEL :
+ {
+ if (Value) {
+ TRACE("Last Pixel Drawing Enabled\n");
+ } else {
+ FIXME("Last Pixel Drawing Disabled, not handled yet\n");
+ }
+ }
+ break;
+
+ case D3DRS_SOFTWAREVERTEXPROCESSING :
+ {
+ if (Value) {
+ TRACE("Software Processing Enabled\n");
+ } else {
+ TRACE("Software Processing Disabled\n");
+ }
+ }
+ break;
+
+ /** not supported */
+ case D3DRS_ZVISIBLE :
+ {
+ LEAVE_GL();
+ return D3DERR_INVALIDCALL;
+ }
+
+ /* Unhandled yet...! */
+ case D3DRS_EDGEANTIALIAS :
+ case D3DRS_WRAP0 :
+ case D3DRS_WRAP1 :
+ case D3DRS_WRAP2 :
+ case D3DRS_WRAP3 :
+ case D3DRS_WRAP4 :
+ case D3DRS_WRAP5 :
+ case D3DRS_WRAP6 :
+ case D3DRS_WRAP7 :
+ case D3DRS_POINTSPRITEENABLE :
+ case D3DRS_MULTISAMPLEANTIALIAS :
+ case D3DRS_MULTISAMPLEMASK :
+ case D3DRS_PATCHEDGESTYLE :
+ case D3DRS_PATCHSEGMENTS :
+ case D3DRS_DEBUGMONITORTOKEN :
+ case D3DRS_POSITIONORDER :
+ case D3DRS_NORMALORDER :
+ /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
+ FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
+ break;
+ default:
+ FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
+ }
+
+ LEAVE_GL();
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+ TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
+ *pValue = This->stateBlock->renderState[State];
+ return D3D_OK;
+}
+
+
+/*****
+ * Get / Set Texture Stage States
+ * TODO: Verify against dx9 definitions
+ *****/
+HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+ union {
+ float f;
+ DWORD d;
+ } tmpvalue;
+
+ /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
+
+ 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)) {
+ TRACE("Attempt to access invalid texture rejected\n");
+ return D3DERR_INVALIDCALL;
+ }
+
+ This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
+ This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
+ This->updateStateBlock->textureState[Stage][Type] = Value;
+
+ /* Handle recording of state blocks */
+ if (This->isRecordingState) {
+ TRACE("Recording... not performing anything\n");
+ return D3D_OK;
+ }
+
+ ENTER_GL();
+
+ /* Make appropriate texture active */
+ VTRACE(("Activating appropriate texture state %ld\n", Stage));
+ if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+ GL_ACTIVETEXTURE(Stage);
+ } else if (Stage > 0) {
+ FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
+ }
+
+ switch (Type) {
+
+ case D3DTSS_MINFILTER :
+ case D3DTSS_MIPFILTER :
+ {
+ DWORD ValueMIN = This->stateBlock->textureState[Stage][D3DTSS_MINFILTER];
+ DWORD ValueMIP = This->stateBlock->textureState[Stage][D3DTSS_MIPFILTER];
+ GLint realVal = GL_LINEAR;
+
+ if (ValueMIN == D3DTEXF_NONE) {
+ /* Doesn't really make sense - Windows just seems to disable
+ mipmapping when this occurs */
+ FIXME("Odd - minfilter of none, just disabling mipmaps\n");
+ realVal = GL_LINEAR;
+ } else if (ValueMIN == D3DTEXF_POINT) {
+ /* GL_NEAREST_* */
+ if (ValueMIP == D3DTEXF_NONE) {
+ realVal = GL_NEAREST;
+ } else if (ValueMIP == D3DTEXF_POINT) {
+ realVal = GL_NEAREST_MIPMAP_NEAREST;
+ } else if (ValueMIP == D3DTEXF_LINEAR) {
+ realVal = GL_NEAREST_MIPMAP_LINEAR;
+ } else {
+ FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
+ realVal = GL_NEAREST;
+ }
+ } else if (ValueMIN == D3DTEXF_LINEAR) {
+ /* GL_LINEAR_* */
+ if (ValueMIP == D3DTEXF_NONE) {
+ realVal = GL_LINEAR;
+ } else if (ValueMIP == D3DTEXF_POINT) {
+ realVal = GL_LINEAR_MIPMAP_NEAREST;
+ } else if (ValueMIP == D3DTEXF_LINEAR) {
+ realVal = GL_LINEAR_MIPMAP_LINEAR;
+ } else {
+ FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
+ realVal = GL_LINEAR;
+ }
+ } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
+ if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
+ if (ValueMIP == D3DTEXF_NONE) {
+ realVal = GL_LINEAR_MIPMAP_LINEAR;
+ } else if (ValueMIP == D3DTEXF_POINT) {
+ realVal = GL_LINEAR_MIPMAP_NEAREST;
+ } else if (ValueMIP == D3DTEXF_LINEAR) {
+ realVal = GL_LINEAR_MIPMAP_LINEAR;
+ } else {
+ FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
+ realVal = GL_LINEAR;
+ }
+ } else {
+ WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
+ realVal = GL_LINEAR;
+ }
+ } else {
+ FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
+ realVal = GL_LINEAR_MIPMAP_LINEAR;
+ }
+
+ TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
+ glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
+ checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
+ /**
+ * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
+ */
+ if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
+ glTexParameteri(This->stateBlock->textureDimensions[Stage],
+ GL_TEXTURE_MAX_ANISOTROPY_EXT,
+ This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
+ checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
+ }
+ }
+ break;
+
+ case D3DTSS_MAGFILTER :
+ {
+ DWORD ValueMAG = This->stateBlock->textureState[Stage][D3DTSS_MAGFILTER];
+ GLint realVal = GL_NEAREST;
+
+ if (ValueMAG == D3DTEXF_POINT) {
+ realVal = GL_NEAREST;
+ } else if (ValueMAG == D3DTEXF_LINEAR) {
+ realVal = GL_LINEAR;
+ } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
+ if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
+ realVal = GL_LINEAR;
+ } else {
+ FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
+ realVal = GL_NEAREST;
+ }
+ } else {
+ FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
+ realVal = GL_NEAREST;
+ }
+ TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
+ glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
+ checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
+ /**
+ * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
+ */
+ if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
+ glTexParameteri(This->stateBlock->textureDimensions[Stage],
+ GL_TEXTURE_MAX_ANISOTROPY_EXT,
+ This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
+ checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
+ }
+ }
+ break;
+
+ case D3DTSS_MAXMIPLEVEL :
+ {
+ /**
+ * Not really the same, but the more apprioprate than nothing
+ */
+ glTexParameteri(This->stateBlock->textureDimensions[Stage],
+ GL_TEXTURE_BASE_LEVEL,
+ This->stateBlock->textureState[Stage][D3DTSS_MAXMIPLEVEL]);
+ checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
+ }
+ break;
+
+ case D3DTSS_MAXANISOTROPY :
+ {
+ if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
+ glTexParameteri(This->stateBlock->textureDimensions[Stage],
+ GL_TEXTURE_MAX_ANISOTROPY_EXT,
+ This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
+ checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
+ }
+ }
+ break;
+
+ case D3DTSS_MIPMAPLODBIAS :
+ {
+ if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
+ tmpvalue.d = Value;
+ glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
+ GL_TEXTURE_LOD_BIAS_EXT,
+ tmpvalue.f);
+ checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
+ }
+ }
+ break;
+
+ case D3DTSS_ALPHAOP :
+ case D3DTSS_COLOROP :
+ {
+
+ if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
+ /* TODO: Disable by making this and all later levels disabled */
+ glDisable(GL_TEXTURE_1D);
+ checkGLcall("Disable GL_TEXTURE_1D");
+ glDisable(GL_TEXTURE_2D);
+ checkGLcall("Disable GL_TEXTURE_2D");
+ glDisable(GL_TEXTURE_3D);
+ checkGLcall("Disable GL_TEXTURE_3D");
+ break; /* Don't bother setting the texture operations */
+ } else {
+ /* Enable only the appropriate texture dimension */
+ if (Type == D3DTSS_COLOROP) {
+ if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
+ glEnable(GL_TEXTURE_1D);
+ checkGLcall("Enable GL_TEXTURE_1D");
+ } else {
+ glDisable(GL_TEXTURE_1D);
+ checkGLcall("Disable GL_TEXTURE_1D");
+ }
+ if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
+ if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
+ glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
+ checkGLcall("Enable GL_TEXTURE_2D");
+ } else {
+ glEnable(GL_TEXTURE_2D);
+ checkGLcall("Enable GL_TEXTURE_2D");
+ }
+ } else {
+ glDisable(GL_TEXTURE_2D);
+ checkGLcall("Disable GL_TEXTURE_2D");
+ }
+ if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
+ glEnable(GL_TEXTURE_3D);
+ checkGLcall("Enable GL_TEXTURE_3D");
+ } else {
+ glDisable(GL_TEXTURE_3D);
+ checkGLcall("Disable GL_TEXTURE_3D");
+ }
+ if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
+ glEnable(GL_TEXTURE_CUBE_MAP_ARB);
+ checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
+ } else {
+ glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+ checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
+ }
+ }
+ }
+ /* Drop through... (Except disable case) */
+ case D3DTSS_COLORARG0 :
+ case D3DTSS_COLORARG1 :
+ case D3DTSS_COLORARG2 :
+ case D3DTSS_ALPHAARG0 :
+ case D3DTSS_ALPHAARG1 :
+ case D3DTSS_ALPHAARG2 :
+ {
+ BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
+ Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
+ if (isAlphaArg) {
+ set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][D3DTSS_ALPHAOP],
+ This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1],
+ This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG2],
+ This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG0]);
+ } else {
+ set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][D3DTSS_COLOROP],
+ This->stateBlock->textureState[Stage][D3DTSS_COLORARG1],
+ This->stateBlock->textureState[Stage][D3DTSS_COLORARG2],
+ This->stateBlock->textureState[Stage][D3DTSS_COLORARG0]);
+ }
+ }
+ break;
+ }
+
+ case D3DTSS_ADDRESSU :
+ case D3DTSS_ADDRESSV :
+ case D3DTSS_ADDRESSW :
+ {
+ GLint wrapParm = GL_REPEAT;
+
+ switch (Value) {
+ case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
+ case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
+ case D3DTADDRESS_BORDER:
+ {
+ if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
+ wrapParm = GL_CLAMP_TO_BORDER_ARB;
+ } else {
+ /* FIXME: Not right, but better */
+ FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
+ wrapParm = GL_REPEAT;
+ }
+ }
+ break;
+ case D3DTADDRESS_MIRROR:
+ {
+ if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
+ wrapParm = GL_MIRRORED_REPEAT_ARB;
+ } else {
+ /* Unsupported in OpenGL pre-1.4 */
+ FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
+ wrapParm = GL_REPEAT;
+ }
+ }
+ break;
+ case D3DTADDRESS_MIRRORONCE:
+ {
+ if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
+ wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
+ } else {
+ FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
+ wrapParm = GL_REPEAT;
+ }
+ }
+ break;
+
+ default:
+ FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
+ wrapParm = GL_REPEAT;
+ }
+
+ switch (Type) {
+ case D3DTSS_ADDRESSU:
+ TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
+ glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
+ checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
+ break;
+ case D3DTSS_ADDRESSV:
+ TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
+ glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
+ checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
+ break;
+ case D3DTSS_ADDRESSW:
+ TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
+ glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
+ checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
+ break;
+ default: /* nop */
+ break; /** stupic compilator */
+ }
+ }
+ break;
+
+ case D3DTSS_BORDERCOLOR :
+ {
+ float col[4];
+ D3DCOLORTOGLFLOAT4(Value, col);
+ TRACE("Setting border color for %x to %lx\n", This->stateBlock->textureDimensions[Stage], Value);
+ glTexParameterfv(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
+ checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
+ }
+ break;
+
+ case D3DTSS_TEXCOORDINDEX :
+ {
+ /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
+
+ /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
+ one flag, you can still specify an index value, which the system uses to
+ determine the texture wrapping mode.
+ eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
+ means use the vertex position (camera-space) as the input texture coordinates
+ for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
+ state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
+ to the TEXCOORDINDEX value */
+
+ /**
+ * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
+ */
+ switch (Value & 0xFFFF0000) {
+ case D3DTSS_TCI_PASSTHRU:
+ /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
+ glDisable(GL_TEXTURE_GEN_S);
+ glDisable(GL_TEXTURE_GEN_T);
+ glDisable(GL_TEXTURE_GEN_R);
+ checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
+ break;
+
+ case D3DTSS_TCI_CAMERASPACEPOSITION:
+ /* CameraSpacePosition means use the vertex position, transformed to camera space,
+ as the input texture coordinates for this stage's texture transformation. This
+ equates roughly to EYE_LINEAR */
+ {
+ float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
+ float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
+ float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
+ float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
+ TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
+ glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
+ glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
+ glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
+ glPopMatrix();
+
+ TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
+ glEnable(GL_TEXTURE_GEN_S);
+ checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+ checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
+ glEnable(GL_TEXTURE_GEN_T);
+ checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+ checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
+ glEnable(GL_TEXTURE_GEN_R);
+ checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
+ glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+ checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
+ }
+ break;
+
+ case D3DTSS_TCI_CAMERASPACENORMAL:
+ {
+ if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
+ float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
+ float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
+ float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
+ float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
+ TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
+ glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
+ glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
+ glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
+ glPopMatrix();
+
+ glEnable(GL_TEXTURE_GEN_S);
+ checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
+ checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
+ glEnable(GL_TEXTURE_GEN_T);
+ checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
+ checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
+ glEnable(GL_TEXTURE_GEN_R);
+ checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
+ glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
+ checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
+ }
+ }
+ break;
+
+ case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
+ {
+ if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
+ float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
+ float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
+ float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
+ float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
+ TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
+ glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
+ glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
+ glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
+ glPopMatrix();
+
+ glEnable(GL_TEXTURE_GEN_S);
+ checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
+ checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
+ glEnable(GL_TEXTURE_GEN_T);
+ checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
+ checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
+ glEnable(GL_TEXTURE_GEN_R);
+ checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
+ glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
+ checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
+ }
+ }
+ break;
+
+ /* Unhandled types: */
+ default:
+ /* Todo: */
+ /* ? disable GL_TEXTURE_GEN_n ? */
+ glDisable(GL_TEXTURE_GEN_S);
+ glDisable(GL_TEXTURE_GEN_T);
+ glDisable(GL_TEXTURE_GEN_R);
+ FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
+ break;
+ }
+ }
+ break;
+
+ /* Unhandled */
+ case D3DTSS_TEXTURETRANSFORMFLAGS :
+ set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
+ break;
+
+ case D3DTSS_BUMPENVMAT00 :
+ case D3DTSS_BUMPENVMAT01 :
+ TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
+ break;
+ case D3DTSS_BUMPENVMAT10 :
+ case D3DTSS_BUMPENVMAT11 :
+ TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
+ break;
+
+ case D3DTSS_BUMPENVLSCALE :
+ TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
+ break;
+
+ case D3DTSS_BUMPENVLOFFSET :
+ TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
+ break;
+
+ case D3DTSS_RESULTARG :
+ TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
+ break;
+
+ default:
+ /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
+ TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
+ }
+
+ LEAVE_GL();
+
+ return D3D_OK;
+}
+
+HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+ TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
+ *pValue = This->updateStateBlock->textureState[Stage][Type];
+ return D3D_OK;
+}
+
+/*****
* Scene related functions
*****/
HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
@@ -1290,11 +2772,17 @@
IWineD3DDeviceImpl_GetIndices,
IWineD3DDeviceImpl_SetViewport,
IWineD3DDeviceImpl_GetViewport,
+ IWineD3DDeviceImpl_SetRenderState,
+ IWineD3DDeviceImpl_GetRenderState,
+ IWineD3DDeviceImpl_SetTextureStageState,
+ IWineD3DDeviceImpl_GetTextureStageState,
IWineD3DDeviceImpl_BeginScene,
IWineD3DDeviceImpl_DrawPrimitive,
IWineD3DDeviceImpl_DrawIndexedPrimitive,
IWineD3DDeviceImpl_DrawPrimitiveUP,
- IWineD3DDeviceImpl_DrawIndexedPrimitiveUP
+ IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
+
+ IWineD3DDeviceImpl_SetupTextureStates
};
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index a2fa093..5b7fcd8 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -1565,7 +1565,7 @@
vp.Height = *(pPresentationParameters->BackBufferHeight);
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
- /* TODO: IWineD3DDevice_SetViewport((LPDIRECT3DDEVICE9) object, &vp); */
+ IWineD3DDevice_SetViewport((IWineD3DDevice *)object, &vp);
}
/* Initialize the current view state */
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 7a23b45..ec6fccc 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -202,14 +202,10 @@
checkGLcall("glMaterialfv");
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->stateBlock->material.Diffuse);
checkGLcall("glMaterialfv");
-#if 0 /* TODO */
- if (This->stateBlock->renderstate[D3DRS_SPECULARENABLE]) {
+ if (This->stateBlock->renderState[D3DRS_SPECULARENABLE]) {
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->stateBlock->material.Specular);
checkGLcall("glMaterialfv");
} else {
-#else
- {
-#endif
float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
checkGLcall("glMaterialfv");
@@ -429,7 +425,7 @@
}
/* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
- /** do we have to Check This->updateStateBlock->renderstate[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
+ /** do we have to Check This->updateStateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
numBlends = ((thisFVF & D3DFVF_POSITION_MASK) >> 1) - 2 +
((FALSE == (thisFVF & D3DFVF_LASTBETA_UBYTE4)) ? 0 : -1); /* WARNING can be < 0 because -2 */
if (numBlends > 0) {
@@ -1502,7 +1498,7 @@
useHW = (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) &&
This->devType != D3DDEVTYPE_REF &&
- !This->stateBlock->renderstate[D3DRS_SOFTWAREVERTEXPROCESSING] &&
+ !This->stateBlock->renderState[D3DRS_SOFTWAREVERTEXPROCESSING] &&
vertex_shader->usage != D3DUSAGE_SOFTWAREPROCESSING);
/** init Constants */
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c
index 61d1fbd..2117a3f 100644
--- a/dlls/wined3d/stateblock.c
+++ b/dlls/wined3d/stateblock.c
@@ -34,6 +34,16 @@
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
@@ -41,6 +51,205 @@
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)) {
+ GL_ACTIVETEXTURE(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;
}
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index d4a6332..0e0223d 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -25,6 +25,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+/*****************************************************************************
+ * Trace formatting of useful values
+ */
const char* debug_d3dformat(D3DFORMAT fmt) {
switch (fmt) {
#define FMT_TO_STR(fmt) case fmt: return #fmt
@@ -140,3 +143,1379 @@
return "unrecognized";
}
}
+
+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";
+ }
+}
+
+/*****************************************************************************
+ * Useful functions mapping GL <-> D3D values
+ */
+GLenum StencilOp(DWORD op) {
+ switch(op) {
+ case D3DSTENCILOP_KEEP : return GL_KEEP;
+ case D3DSTENCILOP_ZERO : return GL_ZERO;
+ case D3DSTENCILOP_REPLACE : return GL_REPLACE;
+ case D3DSTENCILOP_INCRSAT : return GL_INCR;
+ case D3DSTENCILOP_DECRSAT : return GL_DECR;
+ case D3DSTENCILOP_INVERT : return GL_INVERT;
+ case D3DSTENCILOP_INCR : return GL_INCR_WRAP_EXT;
+ case D3DSTENCILOP_DECR : return GL_DECR_WRAP_EXT;
+ default:
+ FIXME("Invalid stencil op %ld\n", op);
+ return GL_ALWAYS;
+ }
+}
+
+/* Set texture operations up - The following avoids lots of ifdefs in this routine!*/
+#if defined (GL_VERSION_1_3)
+# define useext(A) A
+# define combine_ext 1
+#elif defined (GL_EXT_texture_env_combine)
+# define useext(A) A##_EXT
+# define combine_ext 1
+#elif defined (GL_ARB_texture_env_combine)
+# define useext(A) A##_ARB
+# define combine_ext 1
+#else
+# undef combine_ext
+#endif
+
+#if !defined(combine_ext)
+void set_tex_op(LPDIRECT3DDEVICE8 iface, BOOL isAlpha, int Stage, D3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
+{
+ FIXME("Requires opengl combine extensions to work\n");
+ return;
+}
+#else
+/* Setup the texture operations texture stage states */
+void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, D3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
+{
+ #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
+ GLenum src1, src2, src3;
+ GLenum opr1, opr2, opr3;
+ GLenum comb_target;
+ GLenum src0_target, src1_target, src2_target;
+ GLenum opr0_target, opr1_target, opr2_target;
+ GLenum scal_target;
+ GLenum opr=0, invopr, src3_target, opr3_target;
+ BOOL Handled = FALSE;
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+
+ TRACE("Alpha?(%d), Stage:%d Op(%d), a1(%ld), a2(%ld), a3(%ld)\n", isAlpha, Stage, op, arg1, arg2, arg3);
+
+ ENTER_GL();
+
+ /* 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);
+ src1_target = useext(GL_SOURCE1_ALPHA);
+ src2_target = useext(GL_SOURCE2_ALPHA);
+ opr0_target = useext(GL_OPERAND0_ALPHA);
+ opr1_target = useext(GL_OPERAND1_ALPHA);
+ opr2_target = useext(GL_OPERAND2_ALPHA);
+ scal_target = GL_ALPHA_SCALE;
+ }
+ else {
+ comb_target = useext(GL_COMBINE_RGB);
+ src0_target = useext(GL_SOURCE0_RGB);
+ src1_target = useext(GL_SOURCE1_RGB);
+ src2_target = useext(GL_SOURCE2_RGB);
+ opr0_target = useext(GL_OPERAND0_RGB);
+ opr1_target = useext(GL_OPERAND1_RGB);
+ opr2_target = useext(GL_OPERAND2_RGB);
+ scal_target = useext(GL_RGB_SCALE);
+ }
+
+ /* From MSDN (D3DTSS_ALPHAARG1) :
+ 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 && This->stateBlock->textures[Stage] == NULL && arg1 == D3DTA_TEXTURE) {
+ GetSrcAndOpFromValue(D3DTA_DIFFUSE, isAlpha, &src1, &opr1);
+ } else {
+ GetSrcAndOpFromValue(arg1, isAlpha, &src1, &opr1);
+ }
+ GetSrcAndOpFromValue(arg2, isAlpha, &src2, &opr2);
+ GetSrcAndOpFromValue(arg3, isAlpha, &src3, &opr3);
+
+ TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
+
+ Handled = TRUE; /* Assume will be handled */
+
+ /* Other texture operations require special extensions: */
+ if (GL_SUPPORT(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;
+ }
+ switch (op) {
+ case D3DTOP_DISABLE: /* Only for alpha */
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
+ glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
+ checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+ glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
+ 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, 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_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_MODULATE:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ 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, opr1");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_MODULATE2X:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ 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, opr1");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
+ break;
+ case D3DTOP_MODULATE4X:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ 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, opr1");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
+ break;
+
+ case D3DTOP_ADD:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+ 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");
+ 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);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
+ checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+ glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
+ checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+
+ case D3DTOP_ADDSIGNED:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
+ checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
+ 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");
+ 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);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
+ checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+ glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
+ checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+
+ case D3DTOP_ADDSIGNED2X:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
+ checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
+ 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");
+ 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);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
+ checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+ glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
+ checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
+ break;
+
+ case D3DTOP_ADDSMOOTH:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+ 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");
+ 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);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
+ checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
+ switch (opr1) {
+ case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
+ case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
+ case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+ }
+ glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
+ checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+
+ case D3DTOP_BLENDDIFFUSEALPHA:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR));
+ checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR));
+ checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)");
+ glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
+ checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_BLENDTEXTUREALPHA:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
+ checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
+ glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
+ checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_BLENDFACTORALPHA:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT));
+ checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT));
+ checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)");
+ glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
+ checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_BLENDTEXTUREALPHAPM:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+ 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");
+ 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);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
+ checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
+ glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
+ checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_MODULATEALPHA_ADDCOLOR:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
+ glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); /* a0 = src1/opr1 */
+ checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+ glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+ checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); /* a1 = 1 (see docs) */
+ 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); /* a2 = arg2 */
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); /* a3 = src1 alpha */
+ glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
+ checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
+ switch (opr) {
+ case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+ }
+ glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
+ checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_MODULATECOLOR_ADDALPHA:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
+ switch (opr1) {
+ case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+ }
+ 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, invopr);
+ checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+ 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");
+ 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);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
+ checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
+ switch (opr1) {
+ case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+ case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+ }
+ glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
+ checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+ glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+ checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+ switch (opr1) {
+ case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
+ case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
+ case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+ }
+ glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
+ checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
+ switch (opr1) {
+ case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+ }
+ 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, invopr);
+ checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ 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, src3);
+ checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+ 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, src1);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
+ 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");
+ break;
+
+ case D3DTOP_BUMPENVMAP:
+ {
+ if (GL_SUPPORT(NV_TEXTURE_SHADER)) {
+ /*
+ texture unit 0: GL_TEXTURE_2D
+ texture unit 1: GL_DOT_PRODUCT_NV
+ texture unit 2: GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV
+ texture unit 3: GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV
+ */
+ float m[2][2];
+
+ union {
+ float f;
+ DWORD d;
+ } tmpvalue;
+
+ tmpvalue.d = This->stateBlock->textureState[Stage][D3DTSS_BUMPENVMAT00];
+ m[0][0] = tmpvalue.f;
+ tmpvalue.d = This->stateBlock->textureState[Stage][D3DTSS_BUMPENVMAT01];
+ m[0][1] = tmpvalue.f;
+ tmpvalue.d = This->stateBlock->textureState[Stage][D3DTSS_BUMPENVMAT10];
+ m[1][0] = tmpvalue.f;
+ tmpvalue.d = This->stateBlock->textureState[Stage][D3DTSS_BUMPENVMAT11];
+ m[1][1] = tmpvalue.f;
+
+ /*FIXME("Stage %d matrix is (%.2f,%.2f),(%.2f,%.2f)\n", Stage, m[0][0], m[0][1], m[1][0], m[1][0]);*/
+
+ if (FALSE == This->texture_shader_active) {
+ This->texture_shader_active = TRUE;
+ glEnable(GL_TEXTURE_SHADER_NV);
+ }
+
+ /*
+ glEnable(GL_REGISTER_COMBINERS_NV);
+ glCombinerParameteriNV (GL_NUM_GENERAL_COMBINERS_NV, 1);
+ glCombinerInputNV (GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_SIGNED_IDENTITY_NV, GL_RGB);
+ glCombinerInputNV (GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_NONE, GL_UNSIGNED_INVERT_NV, GL_RGB);
+ glCombinerInputNV (GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE2_ARB, GL_SIGNED_IDENTITY_NV, GL_RGB);
+ glCombinerInputNV (GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_NONE, GL_UNSIGNED_INVERT_NV, GL_RGB);
+ glCombinerOutputNV (GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, GL_PRIMARY_COLOR_NV, 0, 0, 0, 0, 0);
+ glCombinerInputNV (GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_SIGNED_IDENTITY_NV, GL_ALPHA);
+ glCombinerInputNV (GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV, GL_NONE, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
+ glCombinerInputNV (GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV, GL_TEXTURE2_ARB, GL_SIGNED_IDENTITY_NV, GL_ALPHA);
+ glCombinerInputNV (GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV, GL_NONE, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
+ glCombinerOutputNV (GL_COMBINER0_NV, GL_ALPHA, GL_DISCARD_NV, GL_DISCARD_NV, GL_PRIMARY_COLOR_NV, 0, 0, 0, 0, 0);
+ glDisable (GL_PER_STAGE_CONSTANTS_NV);
+ glCombinerParameteriNV (GL_COLOR_SUM_CLAMP_NV, 0);
+ glFinalCombinerInputNV (GL_VARIABLE_A_NV, 0, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
+ glFinalCombinerInputNV (GL_VARIABLE_B_NV, 0, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
+ glFinalCombinerInputNV (GL_VARIABLE_C_NV, 0, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
+ glFinalCombinerInputNV (GL_VARIABLE_D_NV, GL_PRIMARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
+ glFinalCombinerInputNV (GL_VARIABLE_E_NV, 0, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
+ glFinalCombinerInputNV (GL_VARIABLE_F_NV, 0, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
+ glFinalCombinerInputNV (GL_VARIABLE_G_NV, GL_PRIMARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
+ */
+ /*
+ int i;
+ for (i = 0; i < Stage; i++) {
+ if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+ GL_ACTIVETEXTURE(i);
+ glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
+ checkGLcall("Activate texture..");
+ } else if (i>0) {
+ FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
+ }
+ }
+ */
+ /*
+ GL_ACTIVETEXTURE(Stage - 1);
+ glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
+ */
+ /*
+ GL_ACTIVETEXTURE(Stage);
+ checkGLcall("Activate texture.. to update const color");
+ glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV);
+ checkGLcall("glTexEnv");
+ glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB + Stage - 1);
+ checkGLcall("glTexEnv");
+ glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, (float*)&m[0]);
+ checkGLcall("glTexEnv");
+ */
+ LEAVE_GL();
+ return;
+ break;
+ }
+ }
+
+ case D3DTOP_BUMPENVMAPLUMINANCE:
+
+ default:
+ Handled = FALSE;
+ }
+ if (Handled) {
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
+ checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
+
+ LEAVE_GL();
+ return;
+ }
+ } /* GL_NV_texture_env_combine4 */
+
+ Handled = TRUE; /* Again, assume handled */
+ switch (op) {
+ case D3DTOP_DISABLE: /* Only for alpha */
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
+ glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
+ checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT");
+ glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
+ checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_SELECTARG1:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_SELECTARG2:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
+ 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, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_MODULATE:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_MODULATE2X:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
+ break;
+ case D3DTOP_MODULATE4X:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
+ break;
+ case D3DTOP_ADD:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_ADDSIGNED:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
+ checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)");
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_ADDSIGNED2X:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
+ checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
+ break;
+ case D3DTOP_SUBTRACT:
+ if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE)) {
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)");
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ } else {
+ FIXME("This version of opengl does not support GL_SUBTRACT\n");
+ }
+ break;
+
+ case D3DTOP_BLENDDIFFUSEALPHA:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
+ checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PRIMARY_COLOR));
+ checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_BLENDTEXTUREALPHA:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
+ checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_BLENDFACTORALPHA:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
+ checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_CONSTANT));
+ checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_BLENDCURRENTALPHA:
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
+ checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PREVIOUS));
+ checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_DOTPRODUCT3:
+ if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3)) {
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
+ } else if (GL_SUPPORT(EXT_TEXTURE_ENV_DOT3)) {
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
+ } else {
+ FIXME("This version of opengl does not support GL_DOT3\n");
+ }
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ 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, src1);
+ checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+ glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+ checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src3");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ break;
+ case D3DTOP_ADDSMOOTH:
+ if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
+ glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+ checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+ switch (opr1) {
+ case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
+ case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
+ case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+ }
+ glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
+ checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ } else
+ Handled = FALSE;
+ break;
+ case D3DTOP_BLENDTEXTUREALPHAPM:
+ if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
+ glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE);
+ checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE");
+ glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA);
+ checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ } else
+ Handled = FALSE;
+ break;
+ case D3DTOP_MODULATEALPHA_ADDCOLOR:
+ if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
+ glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+ checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+ switch (opr1) {
+ case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+ case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+ }
+ glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
+ checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ } else
+ Handled = FALSE;
+ break;
+ case D3DTOP_MODULATECOLOR_ADDALPHA:
+ if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
+ 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");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
+ switch (opr1) {
+ case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+ case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+ }
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ } else
+ Handled = FALSE;
+ break;
+ case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
+ if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
+ glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+ checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+ switch (opr1) {
+ case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+ case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+ }
+ glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
+ checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ } else
+ Handled = FALSE;
+ break;
+ case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
+ if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
+ glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+ checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+ switch (opr1) {
+ case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
+ case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
+ case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+ }
+ glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
+ checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
+ switch (opr1) {
+ case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+ case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+ }
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ } else
+ Handled = FALSE;
+ break;
+ case D3DTOP_MULTIPLYADD:
+ if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
+ glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
+ checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
+ glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
+ checkGLcall("GL_TEXTURE_ENV, src0_target, src3");
+ glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
+ checkGLcall("GL_TEXTURE_ENV, opr0_target, opr3");
+ glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
+ checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
+ glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
+ checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
+ glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+ checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+ glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+ checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+ glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+ checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+ } else
+ Handled = FALSE;
+ break;
+ default:
+ Handled = FALSE;
+ }
+
+ if (Handled) {
+ BOOL combineOK = TRUE;
+ if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
+ DWORD op2;
+
+ if (isAlpha) {
+ op2 = This->stateBlock->textureState[Stage][D3DTSS_COLOROP];
+ } else {
+ op2 = This->stateBlock->textureState[Stage][D3DTSS_ALPHAOP];
+ }
+
+ /* Note: If COMBINE4 in effect can't go back to combine! */
+ 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("Can't use COMBINE4 and COMBINE together, thisop=%d, otherop=%ld, isAlpha(%d)\n", op, op2, isAlpha);
+ LEAVE_GL();
+ return;
+ }
+ }
+ }
+
+ if (combineOK) {
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
+ checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
+
+ LEAVE_GL();
+ return;
+ }
+ }
+
+ LEAVE_GL();
+
+ /* After all the extensions, if still unhandled, report fixme */
+ FIXME("Unhandled texture operation %d\n", op);
+ #undef GLINFO_LOCATION
+}
+#endif
+
+/* Setup this textures matrix according to the texture flags*/
+void set_texture_matrix(const float *smat, DWORD flags)
+{
+ float mat[16];
+
+ glMatrixMode(GL_TEXTURE);
+
+ if (flags == D3DTTFF_DISABLE) {
+ glLoadIdentity();
+ checkGLcall("glLoadIdentity()");
+ return;
+ }
+
+ if (flags == (D3DTTFF_COUNT1|D3DTTFF_PROJECTED)) {
+ ERR("Invalid texture transform flags: D3DTTFF_COUNT1|D3DTTFF_PROJECTED\n");
+ checkGLcall("glLoadIdentity()");
+ return;
+ }
+
+ memcpy(mat, smat, 16*sizeof(float));
+
+ switch (flags & ~D3DTTFF_PROJECTED) {
+ case D3DTTFF_COUNT1: mat[1] = mat[5] = mat[9] = mat[13] = 0;
+ case D3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0;
+ default: mat[3] = mat[7] = mat[11] = 0, mat[15] = 1;
+ }
+
+ if (flags & D3DTTFF_PROJECTED) switch (flags & ~D3DTTFF_PROJECTED) {
+ case D3DTTFF_COUNT2:
+ mat[3] = mat[1], mat[7] = mat[5], mat[11] = mat[9], mat[15] = mat[13];
+ mat[1] = mat[5] = mat[9] = mat[13] = 0;
+ break;
+ case D3DTTFF_COUNT3:
+ mat[3] = mat[2], mat[7] = mat[6], mat[11] = mat[10], mat[15] = mat[14];
+ mat[2] = mat[6] = mat[10] = mat[14] = 0;
+ break;
+ }
+ glLoadMatrixf(mat);
+ checkGLcall("glLoadMatrixf(mat)");
+}
+
+void GetSrcAndOpFromValue(DWORD iValue, BOOL isAlphaArg, GLenum* source, GLenum* operand)
+{
+ BOOL isAlphaReplicate = FALSE;
+ BOOL isComplement = FALSE;
+
+ *operand = GL_SRC_COLOR;
+ *source = GL_TEXTURE;
+
+ /* Catch alpha replicate */
+ if (iValue & D3DTA_ALPHAREPLICATE) {
+ iValue = iValue & ~D3DTA_ALPHAREPLICATE;
+ isAlphaReplicate = TRUE;
+ }
+
+ /* Catch Complement */
+ if (iValue & D3DTA_COMPLEMENT) {
+ iValue = iValue & ~D3DTA_COMPLEMENT;
+ isComplement = TRUE;
+ }
+
+ /* Calculate the operand */
+ if (isAlphaReplicate && !isComplement) {
+ *operand = GL_SRC_ALPHA;
+ } else if (isAlphaReplicate && isComplement) {
+ *operand = GL_ONE_MINUS_SRC_ALPHA;
+ } else if (isComplement) {
+ if (isAlphaArg) {
+ *operand = GL_ONE_MINUS_SRC_ALPHA;
+ } else {
+ *operand = GL_ONE_MINUS_SRC_COLOR;
+ }
+ } else {
+ if (isAlphaArg) {
+ *operand = GL_SRC_ALPHA;
+ } else {
+ *operand = GL_SRC_COLOR;
+ }
+ }
+
+ /* Calculate the source */
+ switch (iValue & D3DTA_SELECTMASK) {
+ case D3DTA_CURRENT: *source = GL_PREVIOUS_EXT;
+ break;
+ case D3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT;
+ break;
+ case D3DTA_TEXTURE: *source = GL_TEXTURE;
+ break;
+ case D3DTA_TFACTOR: *source = GL_CONSTANT_EXT;
+ break;
+ case D3DTA_SPECULAR:
+ /*
+ * According to the GL_ARB_texture_env_combine specs, SPECULAR is
+ * 'Secondary color' and isn't supported until base GL supports it
+ * There is no concept of temp registers as far as I can tell
+ */
+ FIXME("Unhandled texture arg D3DTA_SPECULAR\n");
+ *source = GL_TEXTURE;
+ break;
+
+ default:
+ FIXME("Unrecognized texture arg %ld\n", iValue);
+ *source = GL_TEXTURE;
+ }
+}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 75a470c..f6f4fcb 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -69,18 +69,51 @@
/*****************************************************************************
* Defines
*/
+
+/* GL related defines */
+/* ------------------ */
#define GL_SUPPORT(ExtName) (GLINFO_LOCATION.supported[ExtName] != 0)
#define GL_LIMITS(ExtName) (GLINFO_LOCATION.max_##ExtName)
#define GL_EXTCALL(FuncName) (GLINFO_LOCATION.FuncName)
+#define D3DCOLOR_R(dw) (((float) (((dw) >> 16) & 0xFF)) / 255.0f)
+#define D3DCOLOR_G(dw) (((float) (((dw) >> 8) & 0xFF)) / 255.0f)
+#define D3DCOLOR_B(dw) (((float) (((dw) >> 0) & 0xFF)) / 255.0f)
+#define D3DCOLOR_A(dw) (((float) (((dw) >> 24) & 0xFF)) / 255.0f)
+
+#define D3DCOLORTOGLFLOAT4(dw, vec) \
+ (vec)[0] = D3DCOLOR_R(dw); \
+ (vec)[1] = D3DCOLOR_G(dw); \
+ (vec)[2] = D3DCOLOR_B(dw); \
+ (vec)[3] = D3DCOLOR_A(dw);
+
+/* Note: The following is purely to keep the source code as clear from #ifdefs as possible */
+#if defined(GL_VERSION_1_3)
+#define GL_ACTIVETEXTURE(textureNo) \
+ glActiveTexture(GL_TEXTURE0 + textureNo); \
+ checkGLcall("glActiveTexture");
+#else
+#define GL_ACTIVETEXTURE(textureNo) \
+ glActiveTextureARB(GL_TEXTURE0_ARB + textureNo); \
+ checkGLcall("glActiveTextureARB");
+#endif
+
+/* DirectX Device Limits */
+/* --------------------- */
#define MAX_STREAMS 16 /* Maximum possible streams - used for fixed size arrays
See MaxStreams in MSDN under GetDeviceCaps */
#define HIGHEST_TRANSFORMSTATE 512
/* Highest value in D3DTRANSFORMSTATETYPE */
+#define HIGHEST_RENDER_STATE 209
+ /* Highest D3DRS_ value */
+#define HIGHEST_TEXTURE_STATE 32
+ /* Highest D3DTSS_ value */
#define WINED3D_VSHADER_MAX_CONSTANTS 96
/* Maximum number of constants provided to the shaders */
#define MAX_CLIPPLANES D3DMAXUSERCLIPPLANES
+/* Checking of API calls */
+/* --------------------- */
#define checkGLcall(A) \
{ \
GLint err = glGetError(); \
@@ -91,6 +124,10 @@
} \
}
+/* Trace routines / diagnostics */
+/* ---------------------------- */
+
+/* Dump out a matrix and copy it */
#define conv_mat(mat,gl_mat) \
do { \
TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \
@@ -100,17 +137,6 @@
memcpy(gl_mat, (mat), 16 * sizeof(float)); \
} while (0)
-/* The following is purely to keep the source code as clear from #ifdefs as possible */
-#if defined(GL_VERSION_1_3)
-#define GL_ACTIVETEXTURE(textureNo) \
- glActiveTexture(GL_TEXTURE0 + textureNo); \
- checkGLcall("glActiveTexture");
-#else
-#define GL_ACTIVETEXTURE(textureNo) \
- glActiveTextureARB(GL_TEXTURE0_ARB + textureNo); \
- checkGLcall("glActiveTextureARB");
-#endif
-
/* Macro to dump out the current state of the light chain */
#define DUMP_LIGHT_CHAIN() \
{ \
@@ -121,11 +147,20 @@
} \
}
+/* Trace vector and strided data information */
#define TRACE_VECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w);
#define TRACE_STRIDED(sd,name) TRACE( #name "=(data:%p, stride:%ld, type:%ld)\n", sd->u.s.name.lpData, sd->u.s.name.dwStride, sd->u.s.name.dwType);
+/* Defines used for optimizations */
+
+/* Only reapply what is necessary */
+#define REAPPLY_ALPHAOP 0x0001
+#define REAPPLY_ALL 0xFFFF
+
+/* Advance declaration of structures to satisfy compiler */
typedef struct IWineD3DStateBlockImpl IWineD3DStateBlockImpl;
+/* Global variables */
extern const float identity[16];
/*****************************************************************************
@@ -268,6 +303,11 @@
#define IS_TRACKING 1 /* tracking_parm is tracking diffuse color */
#define NEEDS_TRACKING 2 /* Tracking needs to be enabled when needed */
#define NEEDS_DISABLE 3 /* Tracking needs to be disabled when needed*/
+ UINT srcBlend;
+ UINT dstBlend;
+ UINT alphafunc;
+ UINT stencilfunc;
+ BOOL texture_shader_active; /* TODO: Confirm use is correct */
/* State block related */
BOOL isRecordingState;
@@ -283,6 +323,9 @@
/* For rendering to a texture using glCopyTexImage */
BOOL renderUpsideDown;
+ /* Textures for when no other textures are mapped */
+ UINT dummyTextureName[8];
+
} IWineD3DDeviceImpl;
extern IWineD3DDeviceVtbl IWineD3DDevice_Vtbl;
@@ -380,6 +423,8 @@
BOOL textures[8];
BOOL transform[HIGHEST_TRANSFORMSTATE];
BOOL viewport;
+ BOOL renderState[HIGHEST_RENDER_STATE];
+ BOOL textureState[8][HIGHEST_TEXTURE_STATE];
BOOL clipplane[MAX_CLIPPLANES];
} SAVEDSTATES;
@@ -428,9 +473,20 @@
/* Material */
WINED3DMATERIAL material;
+ /* Indexed Vertex Blending */
+ D3DVERTEXBLENDFLAGS vertex_blend;
+ FLOAT tween_factor;
+
+ /* RenderState */
+ DWORD renderState[HIGHEST_RENDER_STATE];
+
/* Texture */
IWineD3DBaseTexture *textures[8];
int textureDimensions[8];
+
+ /* Texture State Stage */
+ DWORD textureState[8][HIGHEST_TEXTURE_STATE];
+
};
extern IWineD3DStateBlockVtbl IWineD3DStateBlock_Vtbl;
@@ -438,11 +494,21 @@
/*****************************************************************************
* Utility function prototypes
*/
+
+/* Trace routines */
const char* debug_d3dformat(D3DFORMAT fmt);
const char* debug_d3ddevicetype(D3DDEVTYPE devtype);
const char* debug_d3dresourcetype(D3DRESOURCETYPE res);
const char* debug_d3dusage(DWORD usage);
const char* debug_d3dprimitivetype(D3DPRIMITIVETYPE PrimitiveType);
+const char* debug_d3drenderstate(DWORD state);
+const char* debug_d3dtexturestate(DWORD state);
+
+/* Routines for GL <-> D3D values */
+GLenum StencilOp(DWORD op);
+void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, D3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3);
+void set_texture_matrix(const float *smat, DWORD flags);
+void GetSrcAndOpFromValue(DWORD iValue, BOOL isAlphaArg, GLenum* source, GLenum* operand);
#if 0 /* Needs fixing during rework */
/*****************************************************************************
diff --git a/include/wine/wined3d_interface.h b/include/wine/wined3d_interface.h
index c8e11df..073c7b2 100644
--- a/include/wine/wined3d_interface.h
+++ b/include/wine/wined3d_interface.h
@@ -182,11 +182,19 @@
STDMETHOD(GetIndices)(THIS_ IWineD3DIndexBuffer ** ppIndexData,UINT * pBaseVertexIndex) PURE;
STDMETHOD(SetViewport)(THIS_ CONST WINED3DVIEWPORT * pViewport) PURE;
STDMETHOD(GetViewport)(THIS_ WINED3DVIEWPORT * pViewport) PURE;
+ STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE State,DWORD Value) PURE;
+ STDMETHOD(GetRenderState)(THIS_ D3DRENDERSTATETYPE State,DWORD * pValue) PURE;
+ STDMETHOD(SetTextureStageState)(THIS_ DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value) PURE;
+ STDMETHOD(GetTextureStageState)(THIS_ DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD * pValue) PURE;
STDMETHOD(BeginScene)(THIS) PURE;
STDMETHOD(DrawPrimitive)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount) PURE;
STDMETHOD(DrawIndexedPrimitive)(THIS_ D3DPRIMITIVETYPE PrimitiveType,INT baseVIdx, UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) PURE;
STDMETHOD(DrawPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void * pVertexStreamZeroData,UINT VertexStreamZeroStride) PURE;
STDMETHOD(DrawIndexedPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,UINT NumVertexIndices,UINT PrimitiveCount,CONST void * pIndexData,D3DFORMAT IndexDataFormat,CONST void * pVertexStreamZeroData,UINT VertexStreamZeroStride) PURE;
+ /*** Internal use IWineD3D methods ***/
+ STDMETHOD_(void, SetupTextureStates)(THIS_ DWORD Stage, DWORD Flags);
+
+
};
#undef INTERFACE
@@ -221,11 +229,16 @@
#define IWineD3DDevice_GetIndices(p,a,b) (p)->lpVtbl->GetIndices(p,a,b)
#define IWineD3DDevice_SetViewport(p,a) (p)->lpVtbl->SetViewport(p,a)
#define IWineD3DDevice_GetViewport(p,a) (p)->lpVtbl->GetViewport(p,a)
+#define IWineD3DDevice_SetRenderState(p,a,b) (p)->lpVtbl->SetRenderState(p,a,b)
+#define IWineD3DDevice_GetRenderState(p,a,b) (p)->lpVtbl->GetRenderState(p,a,b)
+#define IWineD3DDevice_SetTextureStageState(p,a,b,c) (p)->lpVtbl->SetTextureStageState(p,a,b,c)
+#define IWineD3DDevice_GetTextureStageState(p,a,b,c) (p)->lpVtbl->GetTextureStageState(p,a,b,c)
#define IWineD3DDevice_BeginScene(p) (p)->lpVtbl->BeginScene(p)
#define IWineD3DDevice_DrawPrimitive(p,a,b,c) (p)->lpVtbl->DrawPrimitive(p,a,b,c)
#define IWineD3DDevice_DrawIndexedPrimitive(p,a,b,c,d,e,f) (p)->lpVtbl->DrawIndexedPrimitive(p,a,b,c,d,e,f)
#define IWineD3DDevice_DrawPrimitiveUP(p,a,b,c,d) (p)->lpVtbl->DrawPrimitiveUP(p,a,b,c,d)
#define IWineD3DDevice_DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h)
+#define IWineD3DDevice_SetupTextureStates(p,a,b) (p)->lpVtbl->SetupTextureStates(p,a,b)
#endif
/*****************************************************************************