wined3d: Store dirty states per context.
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 @@
/* 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 @@
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 @@
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 @@
* 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 @@
/* 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 @@
/* 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 @@
}
/* 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 @@
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 @@
} 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 @@
/* 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 @@
* 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 @@
/* 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 @@
* 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 @@
/* 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 @@
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 @@
* 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 @@
* 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 @@
/* 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 @@
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 @@
#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 @@
/* 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 @@
/* 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 @@
/* 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