[5/9] WineD3D: Add a per context structure for context management

Stefan Dösinger stefan at codeweavers.com
Thu Feb 8 15:34:06 CST 2007


-------------- next part --------------
From 65046f3a59d65b84cbacbac8dbbf17d2b54c58b3 Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Fri, 26 Jan 2007 17:58:43 +0100
Subject: [PATCH] WineD3D: Store dirty states per context

---
 dlls/wined3d/device.c          |   18 +++++++++---
 dlls/wined3d/drawprim.c        |    8 +++---
 dlls/wined3d/state.c           |   53 +++++++++++++++++++------------------
 dlls/wined3d/wined3d_private.h |   57 ++++++++++++++++++++-------------------
 4 files changed, 73 insertions(+), 63 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 84d1fa6..1f27916 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -2007,6 +2007,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR
 
     /* Initialize the current view state */
     This->view_ident = 1;
+    This->numContexts = 1;
     This->contexts[0].last_was_rhw = 0;
     glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
     TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
@@ -6978,11 +6979,18 @@ void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
     DWORD rep = StateTable[state].representative;
     DWORD idx;
     BYTE shift;
+    UINT i;
+    WineD3DContext *context;
 
-    if(!rep || isStateDirty(This, rep)) return;
+    if(!rep) return;
 
-    This->dirtyArray[This->numDirtyEntries++] = rep;
-    idx = rep >> 5;
-    shift = rep & 0x1f;
-    This->isStateDirty[idx] |= (1 << shift);
+    for(i = 0; i < This->numContexts; i++) {
+        context = &This->contexts[i];
+        if(isStateDirty(context, rep)) continue;
+
+        context->dirtyArray[context->numDirtyEntries++] = rep;
+        idx = rep >> 5;
+        shift = rep & 0x1f;
+        context->isStateDirty[idx] |= (1 << shift);
+    }
 }
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 8503b36..0d6adf0 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -1202,14 +1202,14 @@ void drawPrimitive(IWineD3DDevice *iface,
     context = &This->contexts[This->activeContext];
 
     /* Apply dirty states */
-    for(i=0; i < This->numDirtyEntries; i++) {
-        dirtyState = This->dirtyArray[i];
+    for(i=0; i < context->numDirtyEntries; i++) {
+        dirtyState = context->dirtyArray[i];
         idx = dirtyState >> 5;
         shift = dirtyState & 0x1f;
-        This->isStateDirty[idx] &= ~(1 << shift);
+        context->isStateDirty[idx] &= ~(1 << shift);
         StateTable[dirtyState].apply(dirtyState, This->stateBlock, context);
     }
-    This->numDirtyEntries = 0; /* This makes the whole list clean */
+    context->numDirtyEntries = 0; /* This makes the whole list clean */
 
     if (TRACE_ON(d3d_draw) && wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
         check_fbo_status(iface);
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index ef71d0d..ee5ba98 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -87,7 +87,7 @@ static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine
      * vertex declaration appplying function calls this function for updating
      */
 
-    if(isStateDirty(stateblock->wineD3DDevice, STATE_VDECL)) {
+    if(isStateDirty(context, STATE_VDECL)) {
         return;
     }
 
@@ -820,7 +820,8 @@ static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine
     /* Depends on the decoded vertex declaration to read the existance of diffuse data.
      * The vertex declaration will call this function if the fixed function pipeline is used.
      */
-    if(isStateDirty(device, STATE_VDECL)) {
+
+    if(isStateDirty(context, STATE_VDECL)) {
         return;
     }
 
@@ -1486,7 +1487,7 @@ static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
     /* The sampler will also activate the correct texture dimensions, so no need to do it here
      * if the sampler for this stage is dirty
      */
-    if(!isStateDirty(stateblock->wineD3DDevice, STATE_SAMPLER(stage))) {
+    if(!isStateDirty(context, STATE_SAMPLER(stage))) {
         if (mapped_stage != -1) activate_dimensions(stage, stateblock);
     }
 
@@ -1734,11 +1735,11 @@ static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine
     }
 
     /* Update the texture matrix */
-    if(!isStateDirty(stateblock->wineD3DDevice, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
+    if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
         transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage), stateblock, context);
     }
 
-    if(!isStateDirty(stateblock->wineD3DDevice, STATE_VDECL) && context->namedArraysLoaded) {
+    if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
         /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
          * source. Call loadVertexData directly because there is no need to reparse the vertex declaration
          * and do all the things linked to it
@@ -1864,7 +1865,7 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont
             glEnable(stateblock->textureDimensions[sampler]);
             checkGLcall("glEnable(stateblock->textureDimensions[sampler])");
         } else if(sampler < stateblock->lowest_disabled_stage) {
-            if(!isStateDirty(stateblock->wineD3DDevice, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
+            if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
                 activate_dimensions(sampler, stateblock);
             }
 
@@ -1878,7 +1879,7 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont
     } else if(sampler < GL_LIMITS(texture_stages)) {
         if(sampler < stateblock->lowest_disabled_stage) {
             /* TODO: What should I do with pixel shaders here ??? */
-            if(!isStateDirty(stateblock->wineD3DDevice, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
+            if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
                 activate_dimensions(sampler, stateblock);
             }
         } /* Otherwise tex_colorop disables the stage */
@@ -1893,8 +1894,8 @@ static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine
     /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
      * has an update pending
      */
-    if(isStateDirty(device, STATE_VDECL) ||
-       isStateDirty(device, STATE_PIXELSHADER)) {
+    if(isStateDirty(context, STATE_VDECL) ||
+       isStateDirty(context, STATE_PIXELSHADER)) {
        return;
     }
     
@@ -1913,7 +1914,7 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
              * make sure to enable them
              */
             for(i=0; i < MAX_SAMPLERS; i++) {
-                if(!isStateDirty(stateblock->wineD3DDevice, STATE_SAMPLER(i))) {
+                if(!isStateDirty(context, STATE_SAMPLER(i))) {
                     sampler(STATE_SAMPLER(i), stateblock, context);
                 }
             }
@@ -1926,13 +1927,13 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
         /* Compile and bind the shader */
         IWineD3DPixelShader_CompileShader(stateblock->pixelShader);
 
-        if(!isStateDirty(stateblock->wineD3DDevice, StateTable[STATE_VSHADER].representative)) {
+        if(!isStateDirty(context, StateTable[STATE_VSHADER].representative)) {
             stateblock->wineD3DDevice->shader_backend->shader_select(
                     (IWineD3DDevice *) stateblock->wineD3DDevice,
                     TRUE,
                     !stateblock->vertexShader ? FALSE : ((IWineD3DVertexShaderImpl *) stateblock->vertexShader)->baseShader.function != NULL);
             
-            if(!isStateDirty(stateblock->wineD3DDevice, STATE_VERTEXSHADERCONSTANT)) {
+            if(!isStateDirty(context, STATE_VERTEXSHADERCONSTANT)) {
                 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
             }
         }
@@ -1942,19 +1943,19 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
          * while it was enabled, so re-apply them.
          */
         for(i=0; i < MAX_TEXTURES; i++) {
-            if(!isStateDirty(stateblock->wineD3DDevice, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
+            if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
                 tex_colorop(STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
             }
         }
         context->last_was_pshader = FALSE;
 
-        if(!isStateDirty(stateblock->wineD3DDevice, StateTable[STATE_VSHADER].representative)) {
+        if(!isStateDirty(context, StateTable[STATE_VSHADER].representative)) {
             stateblock->wineD3DDevice->shader_backend->shader_select(
                     (IWineD3DDevice *) stateblock->wineD3DDevice,
                     FALSE,
                     !stateblock->vertexShader ? FALSE : ((IWineD3DVertexShaderImpl *) stateblock->vertexShader)->baseShader.function != NULL);
 
-            if(!isStateDirty(stateblock->wineD3DDevice, STATE_VERTEXSHADERCONSTANT)) {
+            if(!isStateDirty(context, STATE_VERTEXSHADERCONSTANT)) {
                 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
             }
         }
@@ -2031,7 +2032,7 @@ static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine
     /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
      * No need to do it here if the state is scheduled for update.
      */
-    if(!isStateDirty(stateblock->wineD3DDevice, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
+    if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
         transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
     }
 }
@@ -2692,8 +2693,8 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W
         updateFog = TRUE;
     }
 
-    /* Reapply lighting if it is not scheduled for reapplication already */
-    if(!isStateDirty(device, STATE_RENDER(WINED3DRS_LIGHTING))) {
+    /* Reapply lighting if it is not sheduled for reapplication already */
+    if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
         state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
     }
 
@@ -2726,8 +2727,8 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W
          * or transformed / untransformed was switched
          */
        if(wasrhw != context->last_was_rhw &&
-          !isStateDirty(stateblock->wineD3DDevice, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
-          !isStateDirty(stateblock->wineD3DDevice, STATE_VIEWPORT)) {
+          !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
+          !isStateDirty(context, STATE_VIEWPORT)) {
             transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
         }
         /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
@@ -2742,12 +2743,12 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W
          * dirty
          */
         if(transformed != wasrhw &&
-           !isStateDirty(stateblock->wineD3DDevice, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
-           !isStateDirty(stateblock->wineD3DDevice, STATE_TRANSFORM(WINED3DTS_VIEW))) {
+           !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
+           !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
             transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
         }
 
-        if(!isStateDirty(stateblock->wineD3DDevice, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
+        if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
             state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
         }
     } else {
@@ -2765,10 +2766,10 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W
         /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
          * application
          */
-        if(!isStateDirty(device, STATE_PIXELSHADER)) {
+        if(!isStateDirty(context, STATE_PIXELSHADER)) {
             device->shader_backend->shader_select((IWineD3DDevice *) device, usePixelShaderFunction, useVertexShaderFunction);
 
-            if(!isStateDirty(stateblock->wineD3DDevice, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
+            if(!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
                 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
             }
         }
@@ -2793,7 +2794,7 @@ static void viewport(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCon
 
     stateblock->wineD3DDevice->posFixup[2] = 0.9 / stateblock->viewport.Width;
     stateblock->wineD3DDevice->posFixup[3] = -0.9 / stateblock->viewport.Height;
-    if(!isStateDirty(stateblock->wineD3DDevice, STATE_TRANSFORM(D3DTS_PROJECTION))) {
+    if(!isStateDirty(context, STATE_TRANSFORM(D3DTS_PROJECTION))) {
         transform_projection(STATE_TRANSFORM(D3DTS_PROJECTION), stateblock, context);
     }
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 036d1b4..76bf29c 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -405,23 +405,8 @@ DWORD get_flexible_vertex_size(DWORD d3dvtVertexType);
 #define GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_num) \
     (((((d3dvtVertexType) >> (16 + (2 * (tex_num)))) + 1) & 0x03) + 1)
 
-/* The new context manager that should deal with onscreen and offscreen rendering */
-typedef struct WineD3DContext {
-    /* TODO: Dirty State list                              */
-    /* TODO: Render target / swapchain this ctx belongs to */
-    /* TODO: Thread this ctx belongs to                    */
-
-    /* Stores some inforation about the context state for optimization */
-    BOOL                    last_was_rhw;      /* true iff last draw_primitive was in xyzrhw mode */
-    BOOL                    last_was_pshader;
-    BOOL                    last_was_vshader;
-    BOOL                    last_was_foggy_shader;
-    BOOL                    namedArraysLoaded, numberedArraysLoaded;
-    BOOL                    lastWasPow2Texture[MAX_TEXTURES];
-    GLenum                  tracking_parm;     /* Which source is tracking current colour         */
-} WineD3DContext;
-
 /* Routines and structures related to state management */
+typedef struct WineD3DContext WineD3DContext;
 typedef void (*APPLYSTATEFUNC)(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *ctx);
 
 #define STATE_RENDER(a) (a)
@@ -468,6 +453,31 @@ struct StateEntry
 /* Global state table */
 extern const struct StateEntry StateTable[];
 
+/* The new context manager that should deal with onscreen and offscreen rendering */
+struct WineD3DContext {
+    /* 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/32 + 1]; /* Bitmap to find out quickly if a state is dirty */
+
+    /* TODO: Render target / swapchain this ctx belongs to */
+    /* TODO: Thread this ctx belongs to                    */
+
+    /* Stores some inforation about the context state for optimization */
+    BOOL                    last_was_rhw;      /* true iff last draw_primitive was in xyzrhw mode */
+    BOOL                    last_was_pshader;
+    BOOL                    last_was_vshader;
+    BOOL                    last_was_foggy_shader;
+    BOOL                    namedArraysLoaded, numberedArraysLoaded;
+    BOOL                    lastWasPow2Texture[MAX_TEXTURES];
+    GLenum                  tracking_parm;     /* Which source is tracking current colour         */
+};
+
 /* Routine to fill gl caps for swapchains and IWineD3D */
 BOOL IWineD3DImpl_FillGLCaps(IWineD3D *iface, Display* display);
 
@@ -665,16 +675,6 @@ typedef struct IWineD3DDeviceImpl
     /* 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/32 + 1]; /* Bitmap to find out quickly if a state is dirty */
-
     /* With register combiners we can skip junk texture stages */
     DWORD                     texUnitMap[MAX_SAMPLERS];
     BOOL                      oneToOneTexUnitMap;
@@ -687,15 +687,16 @@ typedef struct IWineD3DDeviceImpl
     /* Context management */
     WineD3DContext          contexts[1];   /* Dynamic array later */
     UINT                    activeContext; /* Only 0 for now      */
+    UINT                    numContexts;   /* Always 1 for now    */
 } IWineD3DDeviceImpl;
 
 extern const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl;
 
 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state);
-static inline BOOL isStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
+static inline BOOL isStateDirty(WineD3DContext *context, DWORD state) {
     DWORD idx = state >> 5;
     BYTE shift = state & 0x1f;
-    return This->isStateDirty[idx] & (1 << shift);
+    return context->isStateDirty[idx] & (1 << shift);
 }
 
 /* Support for IWineD3DResource ::Set/Get/FreePrivateData. I don't think
-- 
1.4.4.3



More information about the wine-patches mailing list