A lot of this code is duplicated. THis will be 'fixed' when we introduce a HAL or when we re-re-re-organize this code :-) Lionel Changelog: - beginning of Material and Light support for D3D7 - new rendering states supported -- Lionel Ulmer - http://www.bbrox.org/
--- /home/ulmer/Wine/wine_base//dlls/ddraw/d3ddevice/main.c 2002-12-26 12:42:50.000000000 +0100 +++ /home/ulmer/Wine/wine_work//dlls/ddraw/d3ddevice/main.c 2002-12-28 17:27:42.000000000 +0100 @@ -162,7 +162,12 @@ DWORD dwFlags) { ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface); - FIXME("(%p/%p)->(%p,%08lx): stub!\n", This, iface, lpNewRenderTarget, dwFlags); + IDirectDrawSurfaceImpl *target_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpNewRenderTarget); + + TRACE("(%p/%p)->(%p,%08lx)\n", This, iface, lpNewRenderTarget, dwFlags); + if (target_impl != This->surface) { + WARN(" Change of rendering target not handled yet !\n"); + } return DD_OK; } @@ -307,7 +312,15 @@ LPD3DMATERIAL7 lpMat) { ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface); - FIXME("(%p/%p)->(%p): stub!\n", This, iface, lpMat); + TRACE("(%p/%p)->(%p)\n", This, iface, lpMat); + + *lpMat = This->current_material; + + if (TRACE_ON(ddraw)) { + TRACE(" returning material : \n"); + dump_D3DMATERIAL7(lpMat); + } + return DD_OK; } @@ -327,7 +340,16 @@ LPD3DLIGHT7 lpLight) { ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface); - FIXME("(%p/%p)->(%08lx,%p): stub!\n", This, iface, dwLightIndex, lpLight); + TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight); + + if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS; + *lpLight = This->light_parameters[dwLightIndex]; + + if (TRACE_ON(ddraw)) { + TRACE(" returning light : \n"); + dump_D3DLIGHT7(lpLight); + } + return DD_OK; } @@ -624,7 +646,13 @@ BOOL* pbEnable) { ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface); - FIXME("(%p/%p)->(%08lx,%p): stub!\n", This, iface, dwLightIndex, pbEnable); + TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, pbEnable); + + if (dwLightIndex > MAX_LIGHTS) *pbEnable = 0; + else *pbEnable = ((0x00000001 << dwLightIndex) & This->active_lights) != 0; + + TRACE(" returning %d.\n", *pbEnable); + return DD_OK; } --- /home/ulmer/Wine/wine_base//dlls/ddraw/d3ddevice/mesa.c 2002-12-27 17:41:29.000000000 +0100 +++ /home/ulmer/Wine/wine_work//dlls/ddraw/d3ddevice/mesa.c 2002-12-28 17:48:03.000000000 +0100 @@ -538,6 +538,8 @@ DWORD dwLightState) { ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface); + IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This; + TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState); switch (dwLightStateType) { @@ -553,17 +555,10 @@ } } break; - case D3DLIGHTSTATE_AMBIENT: { /* 2 */ - float light[4]; - - light[0] = ((dwLightState >> 16) & 0xFF) / 255.0; - light[1] = ((dwLightState >> 8) & 0xFF) / 255.0; - light[2] = ((dwLightState >> 0) & 0xFF) / 255.0; - light[3] = 1.0; - ENTER_GL(); - glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light); - LEAVE_GL(); - } break; + case D3DLIGHTSTATE_AMBIENT: /* 2 */ + /* Call the render_state function... */ + set_render_state(D3DRENDERSTATE_AMBIENT, dwLightState, &(glThis->render_state)); + break; #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break; UNSUP(COLORMODEL); @@ -1469,6 +1464,103 @@ return DD_OK; } +HRESULT WINAPI +GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface, + LPD3DMATERIAL7 lpMat) +{ + ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface); + TRACE("(%p/%p)->(%p)\n", This, iface, lpMat); + + if (TRACE_ON(ddraw)) { + TRACE(" material is : \n"); + dump_D3DMATERIAL7(lpMat); + } + + This->current_material = *lpMat; + + glMaterialfv(GL_FRONT, + GL_DIFFUSE, + (float *) &(This->current_material.u.diffuse)); + glMaterialfv(GL_FRONT, + GL_AMBIENT, + (float *) &(This->current_material.u1.ambient)); + glMaterialfv(GL_FRONT, + GL_SPECULAR, + (float *) &(This->current_material.u2.specular)); + glMaterialfv(GL_FRONT, + GL_EMISSION, + (float *) &(This->current_material.u3.emissive)); + glMaterialf(GL_FRONT, + GL_SHININESS, + This->current_material.u4.power); /* Not sure about this... */ + + return DD_OK; +} + + +HRESULT WINAPI +GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface, + DWORD dwLightIndex, + LPD3DLIGHT7 lpLight) +{ + ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface); + TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight); + + if (TRACE_ON(ddraw)) { + TRACE(" setting light : \n"); + dump_D3DLIGHT7(lpLight); + } + + if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS; + This->set_lights |= 0x00000001 << dwLightIndex; + This->light_parameters[dwLightIndex] = *lpLight; + + switch (lpLight->dltType) { + case D3DLIGHT_DIRECTIONAL: { /* 3 */ + float direction[4]; + + glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient)); + glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse)); + glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular)); + + direction[0] = lpLight->dvDirection.u1.x; + direction[1] = lpLight->dvDirection.u2.y; + direction[2] = lpLight->dvDirection.u3.z; + direction[3] = 0.0; /* This is a directional light */ + + glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) direction); + } break; + + default: WARN(" light type not handled yet...\n"); + } + + return DD_OK; +} + +HRESULT WINAPI +GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface, + DWORD dwLightIndex, + BOOL bEnable) +{ + ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface); + TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable); + + if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS; + + if (bEnable) { + if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) { + /* Set the default parameters.. */ + TRACE(" setting default light parameters...\n"); + GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex])); + } + glEnable(GL_LIGHT0 + dwLightIndex); + } else { + glDisable(GL_LIGHT0 + dwLightIndex); + } + + return DD_OK; +} + #if !defined(__STRICT_ANSI__) && defined(__GNUC__) # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun)) #else @@ -1494,9 +1586,9 @@ XCAST(SetViewport) Main_IDirect3DDeviceImpl_7_SetViewport, XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform, XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport, - XCAST(SetMaterial) Main_IDirect3DDeviceImpl_7_SetMaterial, + XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial, XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial, - XCAST(SetLight) Main_IDirect3DDeviceImpl_7_SetLight, + XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight, XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight, XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState, XCAST(GetRenderState) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderState, @@ -1522,7 +1614,7 @@ XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock, XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock, XCAST(Load) Main_IDirect3DDeviceImpl_7_Load, - XCAST(LightEnable) Main_IDirect3DDeviceImpl_7_LightEnable, + XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable, XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable, XCAST(SetClipPlane) Main_IDirect3DDeviceImpl_7_SetClipPlane, XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane, @@ -1884,6 +1980,7 @@ int num; XVisualInfo template; GLenum buffer; + int light; object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl)); if (object == NULL) return DDERR_OUTOFMEMORY; @@ -1965,6 +2062,29 @@ gl_object->render_state.alpha_func = GL_ALWAYS; /* Here either but it seems logical */ gl_object->render_state.alpha_blend_enable = FALSE; gl_object->render_state.fog_on = FALSE; + gl_object->render_state.stencil_func = GL_ALWAYS; + gl_object->render_state.stencil_mask = 0xFFFFFFFF; + gl_object->render_state.stencil_ref = 0; + gl_object->render_state.stencil_enable = FALSE; + gl_object->render_state.stencil_fail = GL_KEEP; + gl_object->render_state.stencil_zfail = GL_KEEP; + gl_object->render_state.stencil_pass = GL_KEEP; + gl_object->render_state.lighting_enable = FALSE; + gl_object->render_state.specular_enable = FALSE; + gl_object->render_state.color_diffuse = D3DMCS_COLOR1; + gl_object->render_state.color_specular = D3DMCS_COLOR2; + gl_object->render_state.color_ambient = D3DMCS_COLOR2; + gl_object->render_state.color_emissive = D3DMCS_MATERIAL; + + /* Set the various light parameters */ + for (light = 0; light < MAX_LIGHTS; light++) { + /* Only set the fields that are not zero-created */ + object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL; + object->light_parameters[light].dcvDiffuse.u1.r = 1.0; + object->light_parameters[light].dcvDiffuse.u2.g = 1.0; + object->light_parameters[light].dcvDiffuse.u3.b = 1.0; + object->light_parameters[light].dvDirection.u3.z = 1.0; + } /* Allocate memory for the matrices */ object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float)); --- /home/ulmer/Wine/wine_base//dlls/ddraw/d3d_private.h 2002-12-27 11:07:26.000000000 +0100 +++ /home/ulmer/Wine/wine_work//dlls/ddraw/d3d_private.h 2002-12-28 17:25:52.000000000 +0100 @@ -166,6 +166,7 @@ */ #define MAX_TEXTURES 8 +#define MAX_LIGHTS 16 struct IDirect3DDeviceImpl { @@ -189,6 +190,13 @@ D3DMATRIX *view_mat; D3DMATRIX *proj_mat; + /* Current material used in D3D7 mode */ + D3DMATERIAL7 current_material; + + /* Light parameters */ + DWORD active_lights, set_lights; + D3DLIGHT7 light_parameters[MAX_LIGHTS]; + void (*set_context)(IDirect3DDeviceImpl*); HRESULT (*clear)(IDirect3DDeviceImpl *This, DWORD dwCount, @@ -215,6 +223,9 @@ /* Various dump functions */ extern const char *_get_renderstate(D3DRENDERSTATETYPE type); +extern void dump_D3DMATERIAL7(LPD3DMATERIAL7 lpMat); +extern void dump_D3DCOLORVALUE(D3DCOLORVALUE *lpCol); +extern void dump_D3DLIGHT7(LPD3DLIGHT7 lpLight); #define dump_mat(mat) \ TRACE("%f %f %f %f\n", (mat)->_11, (mat)->_12, (mat)->_13, (mat)->_14); \ --- /home/ulmer/Wine/wine_base//dlls/ddraw/d3dcommon.c 2002-12-23 17:35:44.000000000 +0100 +++ /home/ulmer/Wine/wine_work//dlls/ddraw/d3dcommon.c 2002-12-28 17:35:49.000000000 +0100 @@ -163,3 +163,44 @@ if (type >= (sizeof(states) / sizeof(states[0]))) return "ERR"; return states[type]; } + +void +dump_D3DCOLORVALUE(D3DCOLORVALUE *lpCol) +{ + DPRINTF("%f %f %f %f", lpCol->u1.r, lpCol->u2.g, lpCol->u3.b, lpCol->u4.a); +} + +void +dump_D3DVECTOR(D3DVECTOR *lpVec) +{ + DPRINTF("%f %f %f", lpVec->u1.x, lpVec->u2.y, lpVec->u3.z); +} + +void +dump_D3DMATERIAL7(LPD3DMATERIAL7 lpMat) +{ + DPRINTF(" - diffuse : "); dump_D3DCOLORVALUE(&(lpMat->u.diffuse)); DPRINTF("\n"); + DPRINTF(" - ambient : "); dump_D3DCOLORVALUE(&(lpMat->u1.ambient)); DPRINTF("\n"); + DPRINTF(" - specular : "); dump_D3DCOLORVALUE(&(lpMat->u2.specular)); DPRINTF("\n"); + DPRINTF(" - emissive : "); dump_D3DCOLORVALUE(&(lpMat->u3.emissive)); DPRINTF("\n"); + DPRINTF(" - power : %f\n", lpMat->u4.power); +} + +void +dump_D3DLIGHT7(LPD3DLIGHT7 lpLight) +{ + DPRINTF(" - light type : %s\n", (lpLight->dltType == D3DLIGHT_POINT ? "D3DLIGHT_POINT" : + (lpLight->dltType == D3DLIGHT_SPOT ? "D3DLIGHT_SPOT" : + (lpLight->dltType == D3DLIGHT_DIRECTIONAL ? "D3DLIGHT_DIRECTIONAL" : + "UNSUPPORTED")))); + DPRINTF(" - diffuse : "); dump_D3DCOLORVALUE(&(lpLight->dcvDiffuse)); DPRINTF("\n"); + DPRINTF(" - specular : "); dump_D3DCOLORVALUE(&(lpLight->dcvSpecular)); DPRINTF("\n"); + DPRINTF(" - ambient : "); dump_D3DCOLORVALUE(&(lpLight->dcvAmbient)); DPRINTF("\n"); + DPRINTF(" - position : "); dump_D3DVECTOR(&(lpLight->dvPosition)); DPRINTF("\n"); + DPRINTF(" - direction : "); dump_D3DVECTOR(&(lpLight->dvDirection)); DPRINTF("\n"); + DPRINTF(" - dvRange : %f\n", lpLight->dvRange); + DPRINTF(" - dvFalloff : %f\n", lpLight->dvFalloff); + DPRINTF(" - dvAttenuation : %f %f %f\n", lpLight->dvAttenuation0, lpLight->dvAttenuation1, lpLight->dvAttenuation2); + DPRINTF(" - dvTheta : %f\n", lpLight->dvTheta); + DPRINTF(" - dvPhi : %f\n", lpLight->dvPhi); +} --- /home/ulmer/Wine/wine_base//dlls/ddraw/mesa.c 2002-12-27 10:30:26.000000000 +0100 +++ /home/ulmer/Wine/wine_work//dlls/ddraw/mesa.c 2002-12-28 17:30:04.000000000 +0100 @@ -46,6 +46,21 @@ return GL_ALWAYS; } +GLenum convert_D3D_stencilop_to_GL(D3DSTENCILOP dwRenderState) +{ + switch (dwRenderState) { + 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: WARN("D3DSTENCILOP_INCR not properly handled !\n"); return GL_INCR; + case D3DSTENCILOP_DECR: WARN("D3DSTENCILOP_DECR not properly handled !\n"); return GL_DECR; + default: ERR("Unexpected compare type %d !\n", dwRenderState); + } + return GL_KEEP; +} void set_render_state(D3DRENDERSTATETYPE dwRenderStateType, DWORD dwRenderState, RenderState *rs) @@ -400,6 +415,47 @@ case D3DRENDERSTATE_FLUSHBATCH: /* 50 */ break; + case D3DRENDERSTATE_STENCILENABLE: /* 52 */ + if (dwRenderState) + glDisable(GL_STENCIL_TEST); + else + glDisable(GL_STENCIL_TEST); + break; + + case D3DRENDERSTATE_STENCILFAIL: /* 53 */ + rs->stencil_fail = convert_D3D_stencilop_to_GL(dwRenderState); + glStencilOp(rs->stencil_fail, rs->stencil_zfail, rs->stencil_pass); + break; + + case D3DRENDERSTATE_STENCILZFAIL: /* 54 */ + rs->stencil_zfail = convert_D3D_stencilop_to_GL(dwRenderState); + glStencilOp(rs->stencil_fail, rs->stencil_zfail, rs->stencil_pass); + break; + + case D3DRENDERSTATE_STENCILPASS: /* 55 */ + rs->stencil_pass = convert_D3D_stencilop_to_GL(dwRenderState); + glStencilOp(rs->stencil_fail, rs->stencil_zfail, rs->stencil_pass); + break; + + case D3DRENDERSTATE_STENCILFUNC: /* 56 */ + rs->stencil_func = convert_D3D_compare_to_GL(dwRenderState); + glStencilFunc(rs->stencil_func, rs->stencil_ref, rs->stencil_mask); + break; + + case D3DRENDERSTATE_STENCILREF: /* 57 */ + rs->stencil_ref = dwRenderState; + glStencilFunc(rs->stencil_func, rs->stencil_ref, rs->stencil_mask); + break; + + case D3DRENDERSTATE_STENCILMASK: /* 58 */ + rs->stencil_mask = dwRenderState; + glStencilFunc(rs->stencil_func, rs->stencil_ref, rs->stencil_mask); + break; + + case D3DRENDERSTATE_STENCILWRITEMASK: /* 59 */ + glStencilMask(dwRenderState); + break; + case D3DRENDERSTATE_LIGHTING: /* 137 */ /* There will be more to do here once we really support D3D7 Lighting. Should be enough for now to prevent warnings :-) */ @@ -408,6 +464,33 @@ else glDisable(GL_LIGHTING); break; + + case D3DRENDERSTATE_AMBIENT: { /* 139 */ + float light[4]; + + light[0] = ((dwRenderState >> 16) & 0xFF) / 255.0; + light[1] = ((dwRenderState >> 8) & 0xFF) / 255.0; + light[2] = ((dwRenderState >> 0) & 0xFF) / 255.0; + light[3] = ((dwRenderState >> 24) & 0xFF) / 255.0; + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light); + } break; + + case D3DRENDERSTATE_LOCALVIEWER: /* 142 */ + if (dwRenderState) + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); + else + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE); + break; + + case D3DRENDERSTATE_NORMALIZENORMALS: /* 143 */ + if (dwRenderState) { + glEnable(GL_NORMALIZE); + glEnable(GL_RESCALE_NORMAL); + } else { + glDisable(GL_NORMALIZE); + glDisable(GL_RESCALE_NORMAL); + } + break; default: ERR("Unhandled dwRenderStateType %s (%08x) !\n", _get_renderstate(dwRenderStateType), dwRenderStateType); --- /home/ulmer/Wine/wine_base//dlls/ddraw/mesa_private.h 2002-12-27 17:40:23.000000000 +0100 +++ /home/ulmer/Wine/wine_work//dlls/ddraw/mesa_private.h 2002-12-28 17:04:48.000000000 +0100 @@ -69,6 +69,17 @@ GLclampf alpha_ref; BOOLEAN alpha_blend_enable; + /* This is needed for the stencil stuff */ + GLint stencil_ref; + GLuint stencil_mask; + GLenum stencil_func; + BOOLEAN stencil_enable; + GLenum stencil_fail, stencil_zfail, stencil_pass; + + /* This is needed for proper lighting */ + BOOLEAN lighting_enable, specular_enable; + D3DMATERIALCOLORSOURCE color_diffuse, color_specular, color_ambient, color_emissive; + /* This is needed to re-enable fogging when XYZRHW and XYZ primitives are mixed */ BOOLEAN fog_on; } RenderState; @@ -175,8 +186,7 @@ }; #define _dump_colorvalue(s,v) \ - TRACE(" " s " : %f %f %f %f\n", \ - (v).u1.r, (v).u2.g, (v).u3.b, (v).u4.a); + DPRINTF(" - " s); dump_D3DCOLORVALUE(&v); DPRINTF("\n"); /* This structure contains all the function pointers to OpenGL extensions that are used by Wine */ --- /home/ulmer/Wine/wine_base//dlls/ddraw/ddraw/main.c 2002-12-24 15:48:08.000000000 +0100 +++ /home/ulmer/Wine/wine_work//dlls/ddraw/ddraw/main.c 2002-12-28 16:07:44.000000000 +0100 @@ -840,7 +840,7 @@ LPDDCAPS pHELCaps) { ICOM_THIS(IDirectDrawImpl,iface); - TRACE("(%p,%p,%p), stub\n",This,pDriverCaps,pHELCaps); + TRACE("(%p,%p,%p)\n",This,pDriverCaps,pHELCaps); if (pDriverCaps != NULL) { DD_STRUCT_COPY_BYSIZE(pDriverCaps,&This->caps); if (TRACE_ON(ddraw)) {