Stefan Dösinger : wined3d: Implement unfenced updates of double buffered buffers.

Alexandre Julliard julliard at winehq.org
Tue Mar 16 11:49:21 CDT 2010


Module: wine
Branch: master
Commit: 6c53871d302cdd257675b88a01a7b6fc4944b06e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=6c53871d302cdd257675b88a01a7b6fc4944b06e

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Thu Mar 11 12:34:22 2010 +0100

wined3d: Implement unfenced updates of double buffered buffers.

---

 dlls/wined3d/buffer.c          |   83 +++++++++++++++++++++++++++++-----------
 dlls/wined3d/wined3d_private.h |    2 +
 2 files changed, 62 insertions(+), 23 deletions(-)

diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 37c3feb..08d3097 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -767,7 +767,7 @@ static DWORD STDMETHODCALLTYPE buffer_GetPriority(IWineD3DBuffer *iface)
 }
 
 /* The caller provides a GL context */
-static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info)
+static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info, DWORD flags)
 {
         BYTE *map;
         UINT start = 0, len = 0;
@@ -779,6 +779,14 @@ static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined
         {
             GLbitfield mapflags;
             mapflags = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
+            if (flags & WINED3D_BUFFER_DISCARD)
+            {
+                mapflags |= GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT;
+            }
+            else if (flags & WINED3D_BUFFER_NOSYNC)
+            {
+                mapflags |= GL_MAP_UNSYNCHRONIZED_BIT;
+            }
             map = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0,
                                               This->resource.size, mapflags));
             checkGLcall("glMapBufferRange");
@@ -828,8 +836,10 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface)
     BOOL decl_changed = FALSE;
     unsigned int i, j;
     BYTE *data;
+    DWORD flags = This->flags & (WINED3D_BUFFER_NOSYNC | WINED3D_BUFFER_DISCARD);
 
     TRACE("iface %p\n", iface);
+    This->flags &= ~(WINED3D_BUFFER_NOSYNC | WINED3D_BUFFER_DISCARD);
 
     context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
 
@@ -927,6 +937,10 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface)
             ERR("buffer_add_dirty_area failed, this is not expected\n");
             return;
         }
+        /* Avoid unfenced updates, we might overwrite more areas of the buffer than the application
+         * cleared for unsynchronized updates
+         */
+        flags = 0;
     }
 
     if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
@@ -949,7 +963,7 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface)
             return;
         }
 
-        buffer_direct_upload(This, context->gl_info);
+        buffer_direct_upload(This, context->gl_info, flags);
 
         context_release(context);
         return;
@@ -1129,6 +1143,7 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset,
 {
     struct wined3d_buffer *This = (struct wined3d_buffer *)iface;
     LONG count;
+    BOOL dirty = buffer_is_dirty(This);
 
     TRACE("iface %p, offset %u, size %u, data %p, flags %#x\n", iface, offset, size, data, flags);
 
@@ -1140,36 +1155,58 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset,
 
     count = InterlockedIncrement(&This->lock_count);
 
-    if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER) && This->buffer_object)
+    if (This->buffer_object)
     {
-        if(count == 1)
+        if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER))
         {
-            IWineD3DDeviceImpl *device = This->resource.device;
-            struct wined3d_context *context;
-            const struct wined3d_gl_info *gl_info;
-
-            if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
+            if(count == 1)
             {
-                IWineD3DDeviceImpl_MarkStateDirty(This->resource.device, STATE_INDEXBUFFER);
-            }
+                IWineD3DDeviceImpl *device = This->resource.device;
+                struct wined3d_context *context;
+                const struct wined3d_gl_info *gl_info;
 
-            context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
-            gl_info = context->gl_info;
-            ENTER_GL();
-            GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
+                if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
+                {
+                    IWineD3DDeviceImpl_MarkStateDirty(This->resource.device, STATE_INDEXBUFFER);
+                }
 
-            if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
+                context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
+                gl_info = context->gl_info;
+                ENTER_GL();
+                GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
+
+                if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
+                {
+                    GLbitfield mapflags = buffer_gl_map_flags(flags);
+                    This->resource.allocatedMemory = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0,
+                                                                                This->resource.size, mapflags));
+                }
+                else
+                {
+                    This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_READ_WRITE_ARB));
+                }
+                LEAVE_GL();
+                context_release(context);
+            }
+        }
+        else
+        {
+            if (dirty)
             {
-                GLbitfield mapflags = buffer_gl_map_flags(flags);
-                This->resource.allocatedMemory = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0,
-                                                                             This->resource.size, mapflags));
+                if (This->flags & WINED3D_BUFFER_NOSYNC && !(flags & WINED3DLOCK_NOOVERWRITE))
+                {
+                    This->flags &= ~WINED3D_BUFFER_NOSYNC;
+                }
             }
-            else
+            else if(flags & WINED3DLOCK_NOOVERWRITE)
             {
-                This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_READ_WRITE_ARB));
+                This->flags |= WINED3D_BUFFER_NOSYNC;
+            }
+
+            if (flags & WINED3DLOCK_DISCARD)
+            {
+                This->flags |= WINED3D_BUFFER_DISCARD;
             }
-            LEAVE_GL();
-            context_release(context);
         }
     }
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 3c362bf..2271d4e 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2478,6 +2478,8 @@ struct wined3d_map_range
 #define WINED3D_BUFFER_CREATEBO     0x04    /* Attempt to create a buffer object next PreLoad */
 #define WINED3D_BUFFER_DOUBLEBUFFER 0x08    /* Use a vbo and local allocated memory */
 #define WINED3D_BUFFER_FLUSH        0x10    /* Manual unmap flushing */
+#define WINED3D_BUFFER_DISCARD      0x20    /* A DISCARD lock has occured since the last PreLoad */
+#define WINED3D_BUFFER_NOSYNC       0x40    /* All locks since the last PreLoad had NOOVERWRITE set */
 
 struct wined3d_buffer
 {




More information about the wine-cvs mailing list