[2/4] WineD3D: Rework surface dirtification

Stefan Dösinger stefan at codeweavers.com
Tue Mar 6 19:43:09 CST 2007


Ok, I agree that the numerious checks for the offscreen rendering mode are a 
bit ugly.

The issue is that with fbos, TEXTURE and DRAWABLE are the same location, but 
not with other orm methods, and not with depth stencil buffers. I think that 
this dirtification way should be capable of managing the depth stencil blit 
too.

The explanation talks about SFLAG_INPBUFFER. This is wrong, it should be 
SFLAG_INDRAWABLE.
-------------- next part --------------
From 684bdf8a6978eb1b681530c54448e590e2d93edb Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Tue, 6 Mar 2007 21:47:45 +0100
Subject: [PATCH] WineD3D: Rework surface dirtification

Previously the surfaces stored a flag if the system memory copy was ahead of the gl copy(SFLAG_DIRTY) or the
gl copy is ahead(SFLAG_GLDIRTY). The pbuffer copy was 'managed' differently using SFLAG_INPBUFFER and
SFLAG_INTEXTURE.

This patch replaces them with 3 flags, INSYSMEM, INPBUFFER and INTEXTURE which specify which copy contains
the most up to date copy. It is perfectly valid to have more than one of those flags set. One must be set at
least(Except at init, when no content is in the surface yet). When one copy is modified, the flags for the
others are removed.

Basically there are 3 functions used to get each copy up to date:
LockRect: Fetches from the most up to date place into SYSMEM
PreLoad: Fetches into TEXTURE
XXXX: Fetches into pbuffer. Not there yet, unlockrect does that for onscreen/active targets.

The plan is to add a function to copy offscreen textures into the pbuffer when needed(aka not cleared), and
(hopefully) use it for the depth buffer blitting too
---
 dlls/wined3d/context.c           |    5 --
 dlls/wined3d/device.c            |   11 ++++-
 dlls/wined3d/drawprim.c          |   40 ++++++++++++++-
 dlls/wined3d/surface.c           |   99 +++++++++++++++++++++-----------------
 dlls/wined3d/surface_gdi.c       |    1 -
 dlls/wined3d/swapchain.c         |   18 ++++---
 dlls/wined3d/utils.c             |    6 +-
 dlls/wined3d/wined3d_private.h   |   23 ++++-----
 include/wine/wined3d_interface.h |    2 -
 9 files changed, 124 insertions(+), 81 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index b926af0..f7620aa 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -709,12 +709,7 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
             /* Do that before switching the context:
              * Read the back buffer of the old drawable into the destination texture
              */
-            ((IWineD3DSurfaceImpl *) This->lastActiveRenderTarget)->Flags |= SFLAG_INPBUFFER;
-            ((IWineD3DSurfaceImpl *) This->lastActiveRenderTarget)->Flags &= ~SFLAG_INTEXTURE;
-            IWineD3DSurface_AddDirtyRect(This->lastActiveRenderTarget, NULL);
             IWineD3DSurface_PreLoad(This->lastActiveRenderTarget);
-            ((IWineD3DSurfaceImpl *) This->lastActiveRenderTarget)->Flags &= ~SFLAG_INPBUFFER;
-            ((IWineD3DSurfaceImpl *) This->lastActiveRenderTarget)->Flags &= ~SFLAG_INTEXTURE;
         }
         This->lastActiveRenderTarget = target;
         if(oldRenderOffscreen != This->render_offscreen && This->depth_copy_state != WINED3D_DCS_NO_COPY) {
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 3ec9f40..fb4c17b 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -4233,7 +4233,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Coun
     /* Dirtify the target surface for now. If the surface is locked regularily, and an up to date sysmem copy exists,
      * it is most likely more efficient to perform a clear on the sysmem copy too isntead of downloading it
      */
-    ((IWineD3DSurfaceImpl *)This->render_targets[0])->Flags |= SFLAG_GLDIRTY;
+    if(This->render_offscreen && wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
+        ((IWineD3DSurfaceImpl *)This->render_targets[0])->Flags |= SFLAG_INTEXTURE;
+        ((IWineD3DSurfaceImpl *)This->render_targets[0])->Flags &= ~SFLAG_INSYSMEM;
+    } else {
+        ((IWineD3DSurfaceImpl *)This->render_targets[0])->Flags |= SFLAG_INDRAWABLE;
+        ((IWineD3DSurfaceImpl *)This->render_targets[0])->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INSYSMEM);
+    }
     return WINED3D_OK;
 }
 
@@ -4827,7 +4833,8 @@ static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface,
 
     LEAVE_GL();
 
-    ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
+    ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags &= ~SFLAG_INSYSMEM;
+    ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_INTEXTURE;
     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
 
     return WINED3D_OK;
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index c115f2e..4efd3e7 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -1002,6 +1002,9 @@ void drawPrimitive(IWineD3DDevice *iface,
                    int   minIndex) {
 
     IWineD3DDeviceImpl           *This = (IWineD3DDeviceImpl *)iface;
+    IWineD3DSwapChain            *swapchain;
+    IWineD3DBaseTexture          *texture = NULL;
+    IWineD3DSurfaceImpl          *target;
     int i;
 
     /* Signals other modules that a drawing is in progress and the stateblock finalized */
@@ -1009,8 +1012,41 @@ void drawPrimitive(IWineD3DDevice *iface,
 
     /* Invalidate the back buffer memory so LockRect will read it the next time */
     for(i = 0; i < GL_LIMITS(buffers); i++) {
-        if(This->render_targets[i]) {
-            ((IWineD3DSurfaceImpl *) This->render_targets[i])->Flags |= SFLAG_GLDIRTY;
+        target = (IWineD3DSurfaceImpl *) This->render_targets[i];
+        /* TODO: Only do all that if we're going to change anything
+         * Texture container dirtification does not work quite right yet
+         */
+        if(target /*&& target->Flags & (SFLAG_INTEXTURE | SFLAG_INSYSMEM)*/) {
+            swapchain = NULL;
+            texture = NULL;
+
+            if(i == 0) {
+                IWineD3DSurface_GetContainer((IWineD3DSurface *) target, &IID_IWineD3DSwapChain, (void **)&swapchain);
+                if(swapchain) {
+                    /* Onscreen target. Invalidate system memory copy and texture copy */
+                    target->Flags &= ~(SFLAG_INSYSMEM | SFLAG_INTEXTURE);
+                    target->Flags |= SFLAG_INDRAWABLE;
+                    IWineD3DSwapChain_Release(swapchain);
+                } else if(wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
+                    /* Non-FBO target: Invalidate system copy, texture copy and dirtify the container */
+                    IWineD3DSurface_GetContainer((IWineD3DSurface *) target, &IID_IWineD3DBaseTexture, (void **)&texture);
+
+                    if(texture) {
+                        IWineD3DBaseTexture_SetDirty(texture, TRUE);
+                        IWineD3DTexture_Release(texture);
+                    }
+
+                    target->Flags &= ~(SFLAG_INSYSMEM | SFLAG_INTEXTURE);
+                    target->Flags |= SFLAG_INDRAWABLE;
+                } else {
+                    /* FBO offscreen target. Invalidate system memory copy */
+                    target->Flags &= ~SFLAG_INSYSMEM;
+                }
+            } else {
+                /* Must be an fbo render target */
+                target->Flags &= ~SFLAG_INSYSMEM;
+                target->Flags |=  SFLAG_INTEXTURE;
+            }
         }
     }
 
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 772bdbb..c8d39f6 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -446,7 +446,7 @@ void WINAPI IWineD3DSurfaceImpl_SetGlTextureDesc(IWineD3DSurface *iface, UINT te
     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
     TRACE("(%p) : setting textureName %u, target %i\n", This, textureName, target);
     if (This->glDescription.textureName == 0 && textureName != 0) {
-        This->Flags |= SFLAG_DIRTY;
+        This->Flags &= ~SFLAG_INTEXTURE;
         IWineD3DSurface_AddDirtyRect(iface, NULL);
     }
     This->glDescription.textureName = textureName;
@@ -598,7 +598,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED
     /* Whatever surface we have, make sure that there is memory allocated for the downloaded copy */
     if(!This->resource.allocatedMemory) {
         This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 , This->resource.size + 4);
-        This->Flags |= SFLAG_GLDIRTY; /* This is the marker that surface data has to be downloaded */
+        This->Flags &= ~SFLAG_INSYSMEM; /* This is the marker that surface data has to be downloaded */
     }
 
     /* Calculate the correct start address to report */
@@ -651,7 +651,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED
         }
     }
 
-    if((Flags & WINED3DLOCK_DISCARD) || !(This->Flags & SFLAG_GLDIRTY) ) {
+    if((Flags & WINED3DLOCK_DISCARD) || (This->Flags & SFLAG_INSYSMEM)) {
         TRACE("WINED3DLOCK_DISCARD flag passed, or local copy is up to date, not downloading data\n");
         goto lock_end;
     }
@@ -731,7 +731,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED
            This->lockedRect.top == 0 &&
            This->lockedRect.right == This->currentDesc.Width &&
            This->lockedRect.bottom == This->currentDesc.Height) {
-            This->Flags &= ~SFLAG_GLDIRTY;
+            This->Flags |= SFLAG_INSYSMEM;
         }
     } else if(iface == myDevice->stencilBufferTarget) {
         /** the depth stencil in openGL has a format of GL_FLOAT
@@ -750,7 +750,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED
          *             (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
          *
          * Depth Stencil surfaces which are not the current depth stencil target should have their data in a
-         * gl texture(next path), or in local memory(early return because of missing SFLAG_GLDIRTY above). If
+         * gl texture(next path), or in local memory(early return because of set SFLAG_INSYSMEM above). If
          * none of that is the case the problem is not in this function :-)
          ********************************************/
         FIXME("Depth stencil locking not supported yet\n");
@@ -779,7 +779,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED
         }
 
         /* The local copy is now up to date to the opengl one because a full download was done */
-        This->Flags &= ~SFLAG_GLDIRTY;
+        This->Flags |= SFLAG_INSYSMEM;
     }
 
 lock_end:
@@ -803,7 +803,8 @@ lock_end:
         }
     }
 
-    TRACE("returning memory@%p, pitch(%d) dirtyfied(%d)\n", pLockedRect->pBits, pLockedRect->Pitch, This->Flags & SFLAG_DIRTY ? 0 : 1);
+    TRACE("returning memory@%p, pitch(%d) dirtyfied(%d)\n", pLockedRect->pBits, pLockedRect->Pitch,
+          This->Flags & (SFLAG_INDRAWABLE | SFLAG_INTEXTURE) ? 0 : 1);
     return WINED3D_OK;
 }
 
@@ -1061,9 +1062,9 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
         return WINED3DERR_INVALIDCALL;
     }
 
-    TRACE("(%p) : dirtyfied(%d)\n", This, This->Flags & SFLAG_DIRTY ? 1 : 0);
+    TRACE("(%p) : dirtyfied(%d)\n", This, This->Flags & (SFLAG_INDRAWABLE | SFLAG_INTEXTURE) ? 0 : 1);
 
-    if (!(This->Flags & SFLAG_DIRTY)) {
+    if (This->Flags & (SFLAG_INDRAWABLE | SFLAG_INTEXTURE)) {
         TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
         goto unlock_end;
     }
@@ -1130,8 +1131,11 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
         }
         LEAVE_GL();
 
-        /** restore clean dirty state */
-        IWineD3DSurface_CleanDirtyRect(iface);
+        This->dirtyRect.left   = This->currentDesc.Width;
+        This->dirtyRect.top    = This->currentDesc.Height;
+        This->dirtyRect.right  = 0;
+        This->dirtyRect.bottom = 0;
+        This->Flags |= SFLAG_INDRAWABLE;
     } else if(iface == myDevice->stencilBufferTarget) {
         FIXME("Depth Stencil buffer locking is not implemented\n");
     } else {
@@ -1293,7 +1297,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
             HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
         } else {
             /* This is to make LockRect read the gl Texture although memory is allocated */
-            This->Flags |= SFLAG_GLDIRTY;
+            This->Flags &= ~SFLAG_INSYSMEM;
         }
 
         HeapFree(GetProcessHeap(), 0, b_info);
@@ -1687,11 +1691,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
     int width, pitch, outpitch;
     BYTE *mem;
 
-    if (This->Flags & SFLAG_INTEXTURE) {
-        TRACE("Surface already in texture\n");
-        return WINED3D_OK;
-    }
-    if (This->Flags & SFLAG_DIRTY) {
+    if (!(This->Flags & SFLAG_INTEXTURE)) {
         TRACE("Reloading because surface is dirty\n");
     } else if(/* Reload: gl texture has ck, now no ckey is set OR */
               ((This->Flags & SFLAG_GLCKEY) && (!(This->CKeyFlags & DDSD_CKSRCBLT))) ||
@@ -1705,11 +1705,11 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
     } else if(palette9_changed(This)) {
         TRACE("Reloading surface because the d3d8/9 palette was changed\n");
     } else {
-        TRACE("surface isn't dirty\n");
+        TRACE("surface is already in texture\n");
         return WINED3D_OK;
     }
 
-    This->Flags &= ~SFLAG_DIRTY;
+    This->Flags |= SFLAG_INTEXTURE;
 
     /* Resources are placed in system RAM and do not need to be recreated when a device is lost.
     *  These resources are not bound by device size or format restrictions. Because of this,
@@ -1722,7 +1722,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (This->Flags & SFLAG_INPBUFFER) {
+    if (This->Flags & SFLAG_INDRAWABLE) {
         if (This->glDescription.level != 0)
             FIXME("Surface in texture is only supported for level 0\n");
         else if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8 ||
@@ -1734,7 +1734,6 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
             GLint prevRead;
 
             ENTER_GL();
-
             glGetIntegerv(GL_READ_BUFFER, &prevRead);
             vcheckGLcall("glGetIntegerv");
             glReadBuffer(This->resource.wineD3DDevice->offscreenBuffer);
@@ -1755,11 +1754,11 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
 
             LEAVE_GL();
 
-            TRACE("Updating target %d\n", This->glDescription.target);
-            This->Flags |= SFLAG_INTEXTURE;
+            TRACE("Updated target %d\n", This->glDescription.target);
         }
         return WINED3D_OK;
     }
+    /* Otherwise: System memory copy must be most up to date */
 
     if(This->CKeyFlags & DDSD_CKSRCBLT) {
         This->Flags |= SFLAG_GLCKEY;
@@ -1841,6 +1840,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
     if (!(This->Flags & SFLAG_DONOTFREE)) {
         HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
         This->resource.allocatedMemory = NULL;
+        This->Flags &= ~SFLAG_INSYSMEM;
     }
 
     return WINED3D_OK;
@@ -1876,11 +1876,14 @@ HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const ch
 /* check to see if were a 'virtual' texture e.g. were not a pbuffer of texture were a back buffer*/
     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapChain);
 
-    if (swapChain || (This->Flags & SFLAG_INPBUFFER)) { /* if were not a real texture then read the back buffer into a real texture*/
-/* we don't want to interfere with the back buffer so read the data into a temporary texture and then save the data out of the temporary texture */
+    if (This->Flags & SFLAG_INDRAWABLE && !(This->Flags & SFLAG_INTEXTURE)) {
+        /* if were not a real texture then read the back buffer into a real texture */
+        /* we don't want to interfere with the back buffer so read the data into a temporary
+         * texture and then save the data out of the temporary texture
+         */
         GLint prevRead;
         ENTER_GL();
-        FIXME("(%p) This surface needs to be locked before a snapshot can be taken\n", This);
+        TRACE("(%p) Reading render target into texture\n", This);
         glEnable(GL_TEXTURE_2D);
 
         glGenTextures(1, &tmpTexture);
@@ -1913,7 +1916,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const ch
         glReadBuffer(prevRead);
         LEAVE_GL();
 
-    } else { /* bind the real texture */
+    } else { /* bind the real texture, and make sure it up to date */
         IWineD3DSurface_PreLoad(iface);
     }
     allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width  * height * 4);
@@ -1988,25 +1991,13 @@ HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const ch
     return WINED3D_OK;
 }
 
-HRESULT WINAPI IWineD3DSurfaceImpl_CleanDirtyRect(IWineD3DSurface *iface) {
-    IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
-    This->Flags &= ~SFLAG_DIRTY;
-    This->dirtyRect.left   = This->currentDesc.Width;
-    This->dirtyRect.top    = This->currentDesc.Height;
-    This->dirtyRect.right  = 0;
-    This->dirtyRect.bottom = 0;
-    TRACE("(%p) : Dirty?%d, Rect:(%d,%d,%d,%d)\n", This, This->Flags & SFLAG_DIRTY ? 1 : 0, This->dirtyRect.left,
-          This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
-    return WINED3D_OK;
-}
-
 /**
  *   Slightly inefficient way to handle multiple dirty rects but it works :)
  */
 extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) {
     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
     IWineD3DBaseTexture *baseTexture = NULL;
-    This->Flags |= SFLAG_DIRTY;
+    This->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INDRAWABLE);
     if (NULL != pDirtyRect) {
         This->dirtyRect.left   = min(This->dirtyRect.left,   pDirtyRect->left);
         This->dirtyRect.top    = min(This->dirtyRect.top,    pDirtyRect->top);
@@ -2018,7 +2009,7 @@ extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, C
         This->dirtyRect.right  = This->currentDesc.Width;
         This->dirtyRect.bottom = This->currentDesc.Height;
     }
-    TRACE("(%p) : Dirty?%d, Rect:(%d,%d,%d,%d)\n", This, This->Flags & SFLAG_DIRTY, This->dirtyRect.left,
+    TRACE("(%p) : Dirty: yes, Rect:(%d,%d,%d,%d)\n", This, This->dirtyRect.left,
           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
     /* if the container is a basetexture then mark it dirty. */
     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
@@ -2275,6 +2266,9 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine
         }
         glBindTexture(GL_TEXTURE_2D, Src->glDescription.textureName);
         checkGLcall("glBindTexture(Src->glDescription.target, Src->glDescription.textureName)");
+
+        /* For now invalidate the texture copy of the back buffer. Drawable and sysmem copy are untouched */
+        Src->Flags &= ~SFLAG_INTEXTURE;
     }
 
     glReadBuffer(GL_BACK);
@@ -2601,8 +2595,12 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *
             HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
             This->resource.allocatedMemory = NULL;
         } else {
-            This->Flags |= SFLAG_GLDIRTY;
+            This->Flags &= ~SFLAG_INSYSMEM;
         }
+        /* The texture is now most up to date - If the surface is a render target and has a drawable, this
+         * path is never entered
+         */
+        This->Flags |= SFLAG_INTEXTURE;
 
         return WINED3D_OK;
     } else if(Src) {
@@ -2739,7 +2737,16 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *
         LEAVE_GL();
 
         /* TODO: If the surface is locked often, perform the Blt in software on the memory instead */
-        This->Flags |= SFLAG_GLDIRTY;
+        This->Flags &= ~SFLAG_INSYSMEM;
+        /* The surface is now in the drawable. On onscreen surfaces or without fbos the texture
+         * is outdated now
+         */
+        if(dstSwapchain || wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
+            This->Flags |= SFLAG_INDRAWABLE;
+            This->Flags &= ~SFLAG_INTEXTURE;
+        } else {
+            This->Flags |= SFLAG_INTEXTURE;
+        }
 
         return WINED3D_OK;
     } else {
@@ -2972,8 +2979,11 @@ HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) {
     if(This->resource.format == WINED3DFMT_P8 ||
        This->resource.format == WINED3DFMT_A8P8)
     {
+        if(!This->Flags & SFLAG_INSYSMEM) {
+            FIXME("Palette changed with surface that does not have an up to date system memory copy\n");
+        }
         TRACE("Dirtifying surface\n");
-        This->Flags |= SFLAG_DIRTY;
+        This->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INDRAWABLE);
     }
 
     if(This->Flags & SFLAG_DIBSECTION) {
@@ -3237,7 +3247,6 @@ const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
     IWineD3DSurfaceImpl_UpdateOverlayZOrder,
     IWineD3DSurfaceImpl_UpdateOverlay,
     /* Internal use: */
-    IWineD3DSurfaceImpl_CleanDirtyRect,
     IWineD3DSurfaceImpl_AddDirtyRect,
     IWineD3DSurfaceImpl_LoadTexture,
     IWineD3DSurfaceImpl_SaveSnapshot,
diff --git a/dlls/wined3d/surface_gdi.c b/dlls/wined3d/surface_gdi.c
index 508aaae..4565f72 100644
--- a/dlls/wined3d/surface_gdi.c
+++ b/dlls/wined3d/surface_gdi.c
@@ -1600,7 +1600,6 @@ const IWineD3DSurfaceVtbl IWineGDISurface_Vtbl =
     IWineD3DSurfaceImpl_UpdateOverlayZOrder,
     IWineD3DSurfaceImpl_UpdateOverlay,
     /* Internal use: */
-    IWineD3DSurfaceImpl_CleanDirtyRect,
     IWineD3DSurfaceImpl_AddDirtyRect,
     IWineGDISurfaceImpl_LoadTexture,
     IWineGDISurfaceImpl_SaveSnapshot,
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index 48253e9..5fe5c41 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -177,6 +177,8 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO
         /* The cursor must have pow2 sizes */
         cursor.pow2Width = cursor.currentDesc.Width;
         cursor.pow2Height = cursor.currentDesc.Height;
+        /* The surface is in the texture */
+        cursor.Flags |= SFLAG_INTEXTURE;
         /* DDBLT_KEYSRC will cause BltOverride to enable the alpha test with GL_NOTEQUAL, 0.0,
          * which is exactly what we want :-)
          */
@@ -299,13 +301,13 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO
         IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER, 0x00, 1.0, 0);
     }
 
-    if(!(((IWineD3DSurfaceImpl *) This->frontBuffer)->Flags   & SFLAG_GLDIRTY) ||
-       !(((IWineD3DSurfaceImpl *) This->backBuffer[0])->Flags & SFLAG_GLDIRTY) ) {
+    if(((IWineD3DSurfaceImpl *) This->frontBuffer)->Flags   & SFLAG_INSYSMEM ||
+       ((IWineD3DSurfaceImpl *) This->backBuffer[0])->Flags & SFLAG_INSYSMEM ) {
         /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying */
         IWineD3DSurfaceImpl *front = (IWineD3DSurfaceImpl *) This->frontBuffer;
         IWineD3DSurfaceImpl *back = (IWineD3DSurfaceImpl *) This->backBuffer[0];
-        BOOL frontdirty = front->Flags & SFLAG_GLDIRTY;
-        BOOL backdirty = back->Flags & SFLAG_GLDIRTY;
+        BOOL frontuptodate = front->Flags & SFLAG_INSYSMEM;
+        BOOL backuptodate = back->Flags & SFLAG_INSYSMEM;
 
         /* Flip the DC */
         {
@@ -349,10 +351,10 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO
             front->dib.client_memory = back->dib.client_memory;
             back->dib.client_memory = tmp;
         }
-        if(frontdirty) back->Flags |= SFLAG_GLDIRTY;
-        else back->Flags &= ~SFLAG_GLDIRTY;
-        if(backdirty) front->Flags |= SFLAG_GLDIRTY;
-        else front->Flags &= ~SFLAG_GLDIRTY;
+        if(frontuptodate) back->Flags |= SFLAG_INSYSMEM;
+        else back->Flags &= ~SFLAG_INSYSMEM;
+        if(backuptodate) front->Flags |= SFLAG_INSYSMEM;
+        else front->Flags &= ~SFLAG_INSYSMEM;
     }
 
     TRACE("returning\n");
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 9b5a8fd..9c82ef0 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -2508,7 +2508,7 @@ BOOL CalculateTexRect(IWineD3DSurfaceImpl *This, RECT *Rect, float glTexCoord[4]
          * If the texture is dirty, or the part can't be used,
          * re-position the part to load
          */
-        if(!(This->Flags & SFLAG_DIRTY)) {
+        if(This->Flags & SFLAG_INTEXTURE) {
             if(This->glRect.left <= x1 && This->glRect.right >= x2 &&
                This->glRect.top <= y1 && This->glRect.bottom >= x2 ) {
                 /* Ok, the rectangle is ok, re-use it */
@@ -2516,12 +2516,12 @@ BOOL CalculateTexRect(IWineD3DSurfaceImpl *This, RECT *Rect, float glTexCoord[4]
             } else {
                 /* Rectangle is not ok, dirtify the texture to reload it */
                 TRACE("Dirtifying texture to force reload\n");
-                This->Flags |= SFLAG_DIRTY;
+                This->Flags &= ~SFLAG_INTEXTURE;
             }
         }
 
         /* Now if we are dirty(no else if!) */
-        if(This->Flags & SFLAG_DIRTY) {
+        if(!(This->Flags & SFLAG_INTEXTURE)) {
             /* Set the new rectangle. Use the following strategy:
              * 1) Use as big textures as possible.
              * 2) Place the texture part in the way that the requested
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index aca2dc6..9f9c865 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1105,27 +1105,25 @@ HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, RECT *S
 #define SFLAG_OVERSIZE    0x00000001 /* Surface is bigger than gl size, blts only */
 #define SFLAG_CONVERTED   0x00000002 /* Converted for color keying or Palettized */
 #define SFLAG_DIBSECTION  0x00000004 /* Has a DIB section attached for getdc */
-#define SFLAG_DIRTY       0x00000008 /* Surface was locked by the app */
-#define SFLAG_LOCKABLE    0x00000010 /* Surface can be locked */
-#define SFLAG_DISCARD     0x00000020 /* ??? */
-#define SFLAG_LOCKED      0x00000040 /* Surface is locked atm */
-#define SFLAG_INTEXTURE   0x00000080 /* ??? */
-#define SFLAG_INPBUFFER   0x00000100 /* ??? */
+#define SFLAG_LOCKABLE    0x00000008 /* Surface can be locked */
+#define SFLAG_DISCARD     0x00000010 /* ??? */
+#define SFLAG_LOCKED      0x00000020 /* Surface is locked atm */
+#define SFLAG_INTEXTURE   0x00000040 /* The GL texture contains the newest surface content */
+#define SFLAG_INDRAWABLE  0x00000080 /* The gl drawable contains the most up to date data */
+#define SFLAG_INSYSMEM    0x00000100 /* The system memory copy is most up to date */
 #define SFLAG_NONPOW2     0x00000200 /* Surface sizes are not a power of 2 */
 #define SFLAG_DYNLOCK     0x00000400 /* Surface is often locked by the app */
 #define SFLAG_DYNCHANGE   0x00000C00 /* Surface contents are changed very often, implies DYNLOCK */
 #define SFLAG_DCINUSE     0x00001000 /* Set between GetDC and ReleaseDC calls */
-#define SFLAG_GLDIRTY     0x00002000 /* The opengl texture is more up to date than the surface mem */
-#define SFLAG_LOST        0x00004000 /* Surface lost flag for DDraw */
-#define SFLAG_FORCELOAD   0x00008000 /* To force PreLoading of a scratch cursor */
-#define SFLAG_USERPTR     0x00010000 /* The application allocated the memory for this surface */
-#define SFLAG_GLCKEY      0x00020000 /* The gl texture was created with a color key */
+#define SFLAG_LOST        0x00002000 /* Surface lost flag for DDraw */
+#define SFLAG_FORCELOAD   0x00004000 /* To force PreLoading of a scratch cursor */
+#define SFLAG_USERPTR     0x00008000 /* The application allocated the memory for this surface */
+#define SFLAG_GLCKEY      0x00010000 /* The gl texture was created with a color key */
 
 /* In some conditions the surface memory must not be freed:
  * SFLAG_OVERSIZE: Not all data can be kept in GL
  * SFLAG_CONVERTED: Converting the data back would take too long
  * SFLAG_DIBSECTION: The dib code manages the memory
- * SFLAG_DIRTY: GL surface isn't up to date
  * SFLAG_LOCKED: The app requires access to the surface data
  * SFLAG_DYNLOCK: Avoid freeing the data for performance
  * SFLAG_DYNCHANGE: Same reason as DYNLOCK
@@ -1133,7 +1131,6 @@ HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, RECT *S
 #define SFLAG_DONOTFREE  (SFLAG_OVERSIZE   | \
                           SFLAG_CONVERTED  | \
                           SFLAG_DIBSECTION | \
-                          SFLAG_DIRTY      | \
                           SFLAG_LOCKED     | \
                           SFLAG_DYNLOCK    | \
                           SFLAG_DYNCHANGE  | \
diff --git a/include/wine/wined3d_interface.h b/include/wine/wined3d_interface.h
index dfa5125..aaee89e 100644
--- a/include/wine/wined3d_interface.h
+++ b/include/wine/wined3d_interface.h
@@ -1108,7 +1108,6 @@ DECLARE_INTERFACE_(IWineD3DSurface,IWineD3DResource)
     STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD Flags, IWineD3DSurface *Ref) PURE;
     STDMETHOD(UpdateOverlay)(THIS_ RECT *SrcRect, IWineD3DSurface *DstSurface, RECT *DstRect, DWORD Flags, WINEDDOVERLAYFX *FX);
     /* Internally used methods */
-    STDMETHOD(CleanDirtyRect)(THIS) PURE;
     STDMETHOD(AddDirtyRect)(THIS_ CONST RECT* pRect) PURE;
     STDMETHOD(LoadTexture)(THIS) PURE;
     STDMETHOD(SaveSnapshot)(THIS_ const char *filename) PURE;
@@ -1162,7 +1161,6 @@ DECLARE_INTERFACE_(IWineD3DSurface,IWineD3DResource)
 #define IWineD3DSurface_UpdateOverlayZOrder(p, a, b) (p)->lpVtbl->UpdateOverlayZOrder(p, a, b)
 #define IWineD3DSurface_UpdateOverlay(p, a, b, c, d, e) (p)->lpVtbl->UpdateOverlay(p, a, b, c, d, e)
 /*** IWineD3DSurface (Internal, no d3d mapping) methods ***/
-#define IWineD3DSurface_CleanDirtyRect(p)            (p)->lpVtbl->CleanDirtyRect(p)
 #define IWineD3DSurface_AddDirtyRect(p,a)            (p)->lpVtbl->AddDirtyRect(p,a)
 #define IWineD3DSurface_LoadTexture(p)               (p)->lpVtbl->LoadTexture(p)
 #define IWineD3DSurface_SaveSnapshot(p,a)            (p)->lpVtbl->SaveSnapshot(p,a)
-- 
1.4.4.3



More information about the wine-patches mailing list