From eba27af4f13281fbbb1511fe74b8d75df4759716 Mon Sep 17 00:00:00 2001 From: Jason Edmeades Date: Sun, 28 Nov 2004 15:04:41 +0000 Subject: [PATCH] Add Get/Set Transform support, plus BeginScene (does nothing). --- dlls/d3d8/device.c | 3 +- dlls/d3d9/device.c | 12 +-- dlls/wined3d/device.c | 152 ++++++++++++++++++++++++++++++- dlls/wined3d/directx.c | 5 +- dlls/wined3d/resource.c | 1 + dlls/wined3d/stateblock.c | 1 + dlls/wined3d/vertexbuffer.c | 3 +- dlls/wined3d/wined3d_private.h | 39 ++++++-- include/wine/wined3d_interface.h | 6 ++ 9 files changed, 200 insertions(+), 22 deletions(-) diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index 5549d7079de..f4765f9a322 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -1287,8 +1287,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 i HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) { IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; - TRACE("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DDevice_BeginScene(This->WineD3DDevice); } HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) { diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index a1bc2206900..be4acea3f04 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -292,8 +292,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE9 i HRESULT WINAPI IDirect3DDevice9Impl_BeginScene(LPDIRECT3DDEVICE9 iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - TRACE("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DDevice_BeginScene(This->WineD3DDevice); } HRESULT WINAPI IDirect3DDevice9Impl_EndScene(LPDIRECT3DDEVICE9 iface) { @@ -308,17 +307,14 @@ HRESULT WINAPI IDirect3DDevice9Impl_Clear(LPDIRECT3DDEVICE9 iface, DWORD Count return D3D_OK; } -HRESULT WINAPI IDirect3DDevice9Impl_SetTransform(LPDIRECT3DDEVICE9 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) { +HRESULT WINAPI IDirect3DDevice9Impl_SetTransform(LPDIRECT3DDEVICE9 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* lpMatrix) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DDevice_SetTransform(This->WineD3DDevice, State, lpMatrix); } HRESULT WINAPI IDirect3DDevice9Impl_GetTransform(LPDIRECT3DDEVICE9 iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - TRACE("(%p) : for State %d\n", This, State); - memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX)); - return D3D_OK; + return IWineD3DDevice_GetTransform(This->WineD3DDevice, State, pMatrix); } HRESULT WINAPI IDirect3DDevice9Impl_MultiplyTransform(LPDIRECT3DDEVICE9 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) { diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index d71fc2fbed4..610e4c5cc30 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -25,12 +25,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); WINE_DECLARE_DEBUG_CHANNEL(d3d_caps); +#define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info + +/********************************************************** + * Global variable / Constants follow + **********************************************************/ +const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */ /********************************************************** * Utility functions follow **********************************************************/ - /********************************************************** * IWineD3DDevice implementation follows **********************************************************/ @@ -188,6 +193,144 @@ HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT St return D3D_OK; } +/***** + * Get / Set Transform + *****/ +HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + + /* Most of this routine, comments included copied from ddraw tree initially: */ + TRACE("(%p) : Transform State=%d\n", This, d3dts); + + /* Handle recording of state blocks */ + if (This->isRecordingState) { + TRACE("Recording... not performing anything\n"); + This->updateStateBlock->changed.transform[d3dts] = TRUE; + This->updateStateBlock->set.transform[d3dts] = TRUE; + memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX)); + return D3D_OK; + } + + /* + * If the new matrix is the same as the current one, + * we cut off any further processing. this seems to be a reasonable + * optimization because as was noticed, some apps (warcraft3 for example) + * tend towards setting the same matrix repeatedly for some reason. + * + * From here on we assume that the new matrix is different, wherever it matters. + */ + if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) { + TRACE("The app is setting the same matrix over again\n"); + return D3D_OK; + } else { + conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]); + } + + /* + ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord + where ViewMat = Camera space, WorldMat = world space. + + In OpenGL, camera and world space is combined into GL_MODELVIEW + matrix. The Projection matrix stay projection matrix. + */ + + /* Capture the times we can just ignore the change for now */ + if (d3dts == D3DTS_WORLDMATRIX(0)) { + This->modelview_valid = FALSE; + return D3D_OK; + + } else if (d3dts == D3DTS_PROJECTION) { + This->proj_valid = FALSE; + return D3D_OK; + + } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { + /* Indexed Vertex Blending Matrices 256 -> 511 */ + /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */ + FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n"); + return D3D_OK; + } + + /* Now we really are going to have to change a matrix */ + ENTER_GL(); + + if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */ + if (d3dts < GL_LIMITS(textures)) { + int tex = d3dts - D3DTS_TEXTURE0; + GL_ACTIVETEXTURE(tex); +#if 0 /* TODO: */ + set_texture_matrix((float *)lpmatrix, + This->updateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]); +#endif + } + + } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */ + +#if 0 /* TODO: */ + unsigned int k; +#endif + + /* If we are changing the View matrix, reset the light and clipping planes to the new view + * NOTE: We have to reset the positions even if the light/plane is not currently + * enabled, since the call to enable it will not reset the position. + * NOTE2: Apparently texture transforms do NOT need reapplying + */ + + This->modelview_valid = FALSE; + This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float)); +#if 0 /* TODO: */ + PLIGHTINFOEL *lightChain = NULL; +#endif + glMatrixMode(GL_MODELVIEW); + checkGLcall("glMatrixMode(GL_MODELVIEW)"); + glPushMatrix(); + glLoadMatrixf((float *)lpmatrix); + checkGLcall("glLoadMatrixf(...)"); + +#if 0 /* TODO: */ + /* Reset lights */ + lightChain = This->StateBlock->lights; + while (lightChain && lightChain->glIndex != -1) { + glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn); + checkGLcall("glLightfv posn"); + glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn); + checkGLcall("glLightfv dirn"); + lightChain = lightChain->next; + } + /* Reset Clipping Planes if clipping is enabled */ + for (k = 0; k < GL_LIMITS(clipplanes); k++) { + glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]); + checkGLcall("glClipPlane"); + } +#endif + glPopMatrix(); + + } else { /* What was requested!?? */ + WARN("invalid matrix specified: %i\n", d3dts); + } + + /* Release lock, all done */ + LEAVE_GL(); + return D3D_OK; + +} +HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + TRACE("(%p) : for Transform State %d\n", This, State); + memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX)); + return D3D_OK; +} + +/***** + * Scene related functions + *****/ +HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) { + /* At the moment we have no need for any functionality at the beginning + of a scene */ + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + TRACE("(%p) : stub\n", This); + return D3D_OK; +} + /********************************************************** * IUnknown parts follows **********************************************************/ @@ -210,7 +353,7 @@ ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) { ref = InterlockedDecrement(&This->ref); if (ref == 0) { IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock); - IWineD3D_Release(This->WineD3D); + IWineD3D_Release(This->wineD3D); HeapFree(GetProcessHeap(), 0, This); } return ref; @@ -232,5 +375,8 @@ IWineD3DDeviceVtbl IWineD3DDevice_Vtbl = IWineD3DDeviceImpl_SetFVF, IWineD3DDeviceImpl_GetFVF, IWineD3DDeviceImpl_SetStreamSource, - IWineD3DDeviceImpl_GetStreamSource + IWineD3DDeviceImpl_GetStreamSource, + IWineD3DDeviceImpl_SetTransform, + IWineD3DDeviceImpl_GetTransform, + IWineD3DDeviceImpl_BeginScene }; diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 546e39b9612..39c95c893c3 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -31,6 +31,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); WINE_DECLARE_DEBUG_CHANNEL(d3d_caps); +#define GLINFO_LOCATION This->gl_info /********************************************************** * Utility functions follow @@ -1335,8 +1336,8 @@ HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, D3DDEV /* Set up initial COM information */ object->lpVtbl = &IWineD3DDevice_Vtbl; object->ref = 1; - object->WineD3D = iface; - IWineD3D_AddRef(object->WineD3D); + object->wineD3D = iface; + IWineD3D_AddRef(object->wineD3D); object->parent = parent; TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %lx, PresParms: %p, RetDevInt: %p)\n", This, Adapter, DeviceType, diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c index e52d9f8ce3f..bd49fceda90 100644 --- a/dlls/wined3d/resource.c +++ b/dlls/wined3d/resource.c @@ -24,6 +24,7 @@ #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d); +#define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info /* IDirect3DResource IUnknown parts follow: */ HRESULT WINAPI IWineD3DResourceImpl_QueryInterface(IWineD3DResource *iface, REFIID riid, LPVOID *ppobj) diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index d483b0db756..61d1fbd0014 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -23,6 +23,7 @@ #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d); +#define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info HRESULT WINAPI IWineD3DStateBlockImpl_GetParent(IWineD3DStateBlock *iface, IUnknown **pParent) { IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface; diff --git a/dlls/wined3d/vertexbuffer.c b/dlls/wined3d/vertexbuffer.c index 2a6495419d1..21c894fd88b 100644 --- a/dlls/wined3d/vertexbuffer.c +++ b/dlls/wined3d/vertexbuffer.c @@ -24,6 +24,7 @@ #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d); +#define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info /* ******************************************* IWineD3DVertexBuffer IUnknown parts follow @@ -52,7 +53,7 @@ ULONG WINAPI IWineD3DVertexBufferImpl_Release(IWineD3DVertexBuffer *iface) { IWineD3DDevice_Release(This->resource.wineD3DDevice); HeapFree(GetProcessHeap(), 0, This); } else { - IUnknown_Release(This->resource.parent); /* Released the reference to the d3dx VB */ + IUnknown_Release(This->resource.parent); /* Released the reference to the d3dx object */ } return ref; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index c0a2e4064c6..8abcae18c67 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -68,12 +68,13 @@ extern int num_lock; /***************************************************************************** * Defines */ -#define GL_SUPPORT(ExtName) (This->gl_info.supported[ExtName] != 0) - +#define GL_SUPPORT(ExtName) (GLINFO_LOCATION.supported[ExtName] != 0) +#define GL_LIMITS(ExtName) (GLINFO_LOCATION.max_##ExtName) #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 WINED3D_VSHADER_MAX_CONSTANTS 96 /* Maximum number of constants provided to the shaders */ @@ -87,8 +88,30 @@ extern int num_lock; } \ } +#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); \ + TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \ + TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \ + TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \ + 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 + typedef struct IWineD3DStateBlockImpl IWineD3DStateBlockImpl; +extern const float identity[16]; + /***************************************************************************** * IWineD3D implementation structure */ @@ -120,7 +143,7 @@ typedef struct IWineD3DDeviceImpl /* WineD3D Information */ IUnknown *parent; /* TODO - to be a new interface eventually */ - IWineD3D *WineD3D; + IWineD3D *wineD3D; /* X and GL Information */ HWND win_handle; @@ -163,8 +186,8 @@ typedef struct IWineD3DResourceClass /* WineD3DResource Information */ IUnknown *parent; - IWineD3DDevice *wineD3DDevice; D3DRESOURCETYPE resourceType; + IWineD3DDevice *wineD3DDevice; } IWineD3DResourceClass; @@ -173,7 +196,6 @@ typedef struct IWineD3DResourceImpl /* IUnknown & WineD3DResource Information */ IWineD3DResourceVtbl *lpVtbl; IWineD3DResourceClass resource; - } IWineD3DResourceImpl; extern IWineD3DResourceVtbl IWineD3DResource_Vtbl; @@ -222,6 +244,7 @@ extern IWineD3DIndexBufferVtbl IWineD3DIndexBuffer_Vtbl; typedef struct SAVEDSTATES { BOOL fvf; BOOL stream_source[MAX_STREAMS]; + BOOL transform[HIGHEST_TRANSFORMSTATE]; } SAVEDSTATES; struct IWineD3DStateBlockImpl @@ -246,6 +269,10 @@ struct IWineD3DStateBlockImpl UINT stream_stride[MAX_STREAMS]; UINT stream_offset[MAX_STREAMS]; IWineD3DVertexBuffer *stream_source[MAX_STREAMS]; + + /* Transform */ + D3DMATRIX transforms[HIGHEST_TRANSFORMSTATE]; + }; extern IWineD3DStateBlockVtbl IWineD3DStateBlock_Vtbl; diff --git a/include/wine/wined3d_interface.h b/include/wine/wined3d_interface.h index da8108fafb0..fee8a9a526d 100644 --- a/include/wine/wined3d_interface.h +++ b/include/wine/wined3d_interface.h @@ -152,6 +152,9 @@ DECLARE_INTERFACE_(IWineD3DDevice,IUnknown) STDMETHOD(GetFVF)(THIS_ DWORD * pfvf) PURE; STDMETHOD(SetStreamSource)(THIS_ UINT StreamNumber,IWineD3DVertexBuffer * pStreamData,UINT Offset,UINT Stride) PURE; STDMETHOD(GetStreamSource)(THIS_ UINT StreamNumber,IWineD3DVertexBuffer ** ppStreamData,UINT *pOffset, UINT * pStride) PURE; + STDMETHOD(SetTransform)(THIS_ D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX * pMatrix) PURE; + STDMETHOD(GetTransform)(THIS_ D3DTRANSFORMSTATETYPE State,D3DMATRIX * pMatrix) PURE; + STDMETHOD(BeginScene)(THIS) PURE; }; #undef INTERFACE @@ -169,6 +172,9 @@ DECLARE_INTERFACE_(IWineD3DDevice,IUnknown) #define IWineD3DDevice_GetFVF(p,a) (p)->lpVtbl->GetFVF(p,a) #define IWineD3DDevice_SetStreamSource(p,a,b,c,d) (p)->lpVtbl->SetStreamSource(p,a,b,c,d) #define IWineD3DDevice_GetStreamSource(p,a,b,c,d) (p)->lpVtbl->GetStreamSource(p,a,b,c,d) +#define IWineD3DDevice_SetTransform(p,a,b) (p)->lpVtbl->SetTransform(p,a,b) +#define IWineD3DDevice_GetTransform(p,a,b) (p)->lpVtbl->GetTransform(p,a,b) +#define IWineD3DDevice_BeginScene(p) (p)->lpVtbl->BeginScene(p) #endif /*****************************************************************************