From 1a92f3df3784c2d97d9c0479cb8505bda83006d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Tue, 9 Feb 2010 13:37:02 +0100
Subject: [PATCH 06/12] WineD3D: Partially implement unserialized buffers with the apple extension

This patch makes use of unserialized buffer accesses provided by
GL_APPLE_flush_buffer_range. It doesn't yet implement synchronization.
If the app doesn't pass either NOOVERWRITE or DISCARD the unsychronized
maps are dropped.
---
 dlls/wined3d/buffer.c          |   27 +++++++++++++++++++++++++++
 dlls/wined3d/wined3d_private.h |    1 +
 2 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index b423072..aa90fd3 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -107,6 +107,8 @@ static void delete_gl_buffer(struct wined3d_buffer *This)
     checkGLcall("glDeleteBuffersARB");
     LEAVE_GL();
     This->buffer_object = 0;
+
+    This->flags &= ~WINED3D_BUFFER_APPLESYNC;
 }
 
 /* Context activation is done by the caller. */
@@ -169,6 +171,10 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This)
             GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE));
             checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE)");
             This->flags |= WINED3D_BUFFER_FLUSH;
+
+            GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE));
+            checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE)");
+            This->flags |= WINED3D_BUFFER_APPLESYNC;
         }
         /* No setup is needed here for GL_ARB_map_buffer_range */
     }
@@ -1092,6 +1098,26 @@ static GLbitfield buffer_gl_map_flags(DWORD d3d_flags)
     return ret;
 }
 
+/* The caller provides a context and GL locking and binds the buffer */
+static void buffer_sync_apple(struct wined3d_buffer *This, DWORD flags)
+{
+    /* No fencing needs to be done if the app promises not to overwrite
+     * existing data */
+    if(flags & WINED3DLOCK_NOOVERWRITE) return;
+    if(flags & WINED3DLOCK_DISCARD)
+    {
+        GL_EXTCALL(glBufferDataARB(This->buffer_type_hint, This->resource.size, NULL, This->buffer_object_usage));
+        checkGLcall("glBufferDataARB\n");
+        return;
+    }
+
+    /* Drop the unserialized updates for now */
+    FIXME("Implement fences for unserialized buffers\n");
+    GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE));
+    checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)");
+    This->flags &= ~WINED3D_BUFFER_APPLESYNC;
+}
+
 static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset, UINT size, BYTE **data, DWORD flags)
 {
     struct wined3d_buffer *This = (struct wined3d_buffer *)iface;
@@ -1133,6 +1159,7 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset,
             }
             else
             {
+                if(This->flags & WINED3D_BUFFER_APPLESYNC) buffer_sync_apple(This, flags);
                 This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_READ_WRITE_ARB));
             }
             LEAVE_GL();
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 55b8cee..8bc6cb6 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2402,6 +2402,7 @@ 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_APPLESYNC    0x20    /* Using sync as in GL_APPLE_flush_buffer_range */
 
 struct wined3d_buffer
 {
-- 
1.6.4.4

