From e0b86ee56d5e91feaff5384ed5231f2b419fd8b3 Mon Sep 17 00:00:00 2001 From: Stefan Doesinger Date: Mon, 18 Dec 2006 20:18:54 +0100 Subject: [PATCH] WineD3D: Add state dirtification infrastructure --- dlls/wined3d/device.c | 13 +++++++++++++ dlls/wined3d/drawprim.c | 12 ++++++++++++ dlls/wined3d/wined3d_private.h | 20 ++++++++++++++++++++ 3 files changed, 45 insertions(+), 0 deletions(-) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 685cdf9..217f666 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -7084,3 +7084,16 @@ const DWORD SavedVertexStates_T[NUM_SAVE const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = { WINED3DSAMP_DMAPOFFSET }; + +void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) { + DWORD rep = StateTable[state].representative; + DWORD idx; + BYTE shift; + + if(!rep || isStateDirty(This, rep)) return; + + This->dirtyArray[This->numDirtyEntries++] = rep; + idx = rep >> 5; + shift = rep & 0x1f; + This->isStateDirty[idx] |= (1 << shift); +} diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index a560084..06a86ae 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -2129,6 +2129,8 @@ void drawPrimitive(IWineD3DDevice *iface IWineD3DSwapChainImpl *swapchain; int i; BOOL fixup = FALSE; + DWORD dirtyState, idx; + BYTE shift; BOOL lighting_changed, lighting_original = FALSE; @@ -2163,6 +2165,16 @@ void drawPrimitive(IWineD3DDevice *iface /* Ok, we will be updating the screen from here onwards so grab the lock */ ENTER_GL(); + /* Apply dirty states */ + for(i=0; i < This->numDirtyEntries; i++) { + dirtyState = This->dirtyArray[i]; + idx = dirtyState >> 5; + shift = dirtyState & 0x1f; + This->isStateDirty[idx] &= ~(1 << shift); + StateTable[dirtyState].apply(dirtyState, This->stateBlock); + } + This->numDirtyEntries = 0; /* This makes the whole list clean */ + if(DrawPrimStrideData) { /* Note: this is a ddraw fixed-function code path */ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index da3fbe9..e01a529 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -413,6 +413,8 @@ typedef void (*APPLYSTATEFUNC)(DWORD sta #define STATE_RENDER(a) (a) #define STATE_IS_RENDER(a) ((a) >= STATE_RENDER(1) && (a) <= STATE_RENDER(WINEHIGHEST_RENDER_STATE)) +#define STATE_HIGHEST (STATE_RENDER(WINEHIGHEST_RENDER_STATE)) + struct StateEntry { DWORD representative; @@ -627,10 +629,28 @@ #define NEEDS_DI /* Final position fixup constant */ float posFixup[4]; + + /* State dirtification + * dirtyArray is an array that contains markers for dirty states. numDirtyEntries states are dirty, their numbers are in indices + * 0...numDirtyEntries - 1. isStateDirty is a redundant copy of the dirtyArray. Technically only one of them would be needed, + * but with the help of both it is easy to find out if a state is dirty(just check the array index), and for applying dirty states + * only numDirtyEntries array elements have to be checked, not STATE_HIGHEST states. + */ + DWORD dirtyArray[STATE_HIGHEST + 1]; /* Won't get bigger than that, a state is never marked dirty 2 times */ + DWORD numDirtyEntries; + DWORD isStateDirty[(STATE_HIGHEST) / (sizeof(DWORD) * 8) + 1]; /* Bitmap to find out quickly if a state is dirty */ + } IWineD3DDeviceImpl; extern const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl; +void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state); +static inline BOOL isStateDirty(IWineD3DDeviceImpl *This, DWORD state) { + DWORD idx = state >> 5; + BYTE shift = state & 0x1f; + return This->isStateDirty[idx] & (1 << shift); +} + /* Support for IWineD3DResource ::Set/Get/FreePrivateData. I don't think * anybody uses it for much so a good implementation is optional. */ typedef struct PrivateData -- 1.4.2.4