[1] WineD3D: Add the state dirtification infrastructure
Stefan Dösinger
stefan at codeweavers.com
Fri Dec 15 11:31:52 CST 2006
This patch adds the dirty list infrastructure. A dirty marker consists of a
DWORD containing the state it marks dirty, and the list structure to build
the list.
The wined3ddevice has 3 new members:
dirtyStateList: The list of dirty states. This will be moved to a per-context
stucture once we add multithreading support
freeListElems: A list containing unused dirty markers to avoid unnecessary
HeapAlloc/HeapFree calls. I have seen D3D games spending 15% cpu time in the
Heap code, we don't want to increase that.
dirtyStates: An array that tells if a state is dirty. It is used to avoid
double dirtification. I do not use the stateblock->changed.XXXX[] array
because this is used for different purposes in the stateblock code. Ivan, do
we still need it?
-------------- next part --------------
From e1e113df65c888a14d8a54bc073a15858b4fd986 Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Fri, 15 Dec 2006 17:46:47 +0100
Subject: [PATCH] WineD3D: Add state dirtification infrastructure
---
dlls/wined3d/device.c | 36 ++++++++++++++++++++++++++++++++++++
dlls/wined3d/directx.c | 3 +++
dlls/wined3d/drawprim.c | 10 ++++++++++
dlls/wined3d/wined3d_private.h | 17 +++++++++++++++++
4 files changed, 66 insertions(+), 0 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index ff3c987..af6876a 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -568,6 +568,8 @@ static ULONG WINAPI IWineD3DDeviceImpl_R
TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
if (!refCount) {
+ struct list *entry, *entry2;
+
if (This->fbo) {
GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo));
}
@@ -604,6 +606,19 @@ static ULONG WINAPI IWineD3DDeviceImpl_R
dumpResources(This->resources);
}
+ /* Free the dirty state list and the free elem list */
+ LIST_FOR_EACH_SAFE(entry, entry2, &This->dirtyStateList)
+ {
+ struct dirtyMarker *marker = LIST_ENTRY(entry, struct dirtyMarker, entry);
+ list_remove(&marker->entry);
+ HeapFree(GetProcessHeap(), 0, marker);
+ }
+ LIST_FOR_EACH_SAFE(entry, entry2, &This->freeListElems)
+ {
+ struct dirtyMarker *marker = LIST_ENTRY(entry, struct dirtyMarker, entry);
+ list_remove(&marker->entry);
+ HeapFree(GetProcessHeap(), 0, marker);
+ }
IWineD3D_Release(This->wineD3D);
This->wineD3D = NULL;
@@ -7088,3 +7103,24 @@ 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;
+ struct list *ret;
+ struct dirtyMarker *marker;
+
+ if(!rep || This->dirtyStates[rep]) return;
+
+ /* Look if there is an element in our free elem list, otherwise alloc a new one */
+ ret = list_head(&This->freeListElems);
+ if(!ret) {
+ TRACE("creating new elem\n");
+ marker = HeapAlloc(GetProcessHeap(), 0, sizeof(struct dirtyMarker));
+ } else {
+ list_remove(ret);
+ marker = LIST_ENTRY(ret, struct dirtyMarker, entry);
+ }
+ marker->state = rep;
+ list_add_tail(&This->dirtyStateList, &marker->entry);
+ This->dirtyStates[rep] = TRUE;
+}
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 6e97cc3..b592c01 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -2458,6 +2458,9 @@ static HRESULT WINAPI IWineD3DImpl_Crea
object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
DeleteDC(hDC);
+ list_init(&object->dirtyStateList);
+ list_init(&object->freeListElems);
+
return WINED3D_OK;
create_device_error:
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index a560084..38042ec 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;
+ struct list *entry;
+ struct dirtyMarker *dirtyState;
BOOL lighting_changed, lighting_original = FALSE;
@@ -2163,6 +2165,14 @@ void drawPrimitive(IWineD3DDevice *iface
/* Ok, we will be updating the screen from here onwards so grab the lock */
ENTER_GL();
+ /* Apply dirty states */
+ LIST_FOR_EACH(entry, &This->dirtyStateList) {
+ dirtyState = LIST_ENTRY(entry, struct dirtyMarker, entry);
+ This->dirtyStates[dirtyState->state] = 0;
+ StateTable[dirtyState->state].apply(dirtyState->state, This->stateBlock);
+ }
+ list_move_tail(&This->freeListElems, &This->dirtyStateList);
+
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 2f5e887..5025fd0 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;
@@ -422,6 +424,13 @@ struct StateEntry
/* Global state table */
extern const struct StateEntry StateTable[];
+/* Functions for state dirtification */
+struct dirtyMarker
+{
+ struct list entry;
+ DWORD state;
+};
+
/* Routine to fill gl caps for swapchains and IWineD3D */
BOOL IWineD3DImpl_FillGLCaps(IWineD3D *iface, Display* display);
@@ -627,10 +636,18 @@ #define NEEDS_DI
/* Final position fixup constant */
float posFixup[4];
+
+ /* State dirtification. */
+ struct list dirtyStateList; /* TODO: Move this into the ctx */
+ struct list freeListElems; /* To avoid too much alloc / free calls */
+ DWORD dirtyStates[STATE_HIGHEST + 1];
+
} IWineD3DDeviceImpl;
extern const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl;
+void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state);
+
/* 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
More information about the wine-patches
mailing list