wined3d: Use glMapBuffer for 1:1 uploads in PreLoad.
authorStefan Dösinger <stefan@codeweavers.com>
Thu, 11 Mar 2010 11:23:19 +0000 (12:23 +0100)
committerAlexandre Julliard <julliard@winehq.org>
Tue, 16 Mar 2010 16:02:43 +0000 (17:02 +0100)
This is needed to take advantage of asynchronous uploads with double buffered buffers

dlls/wined3d/buffer.c

index 86d6fb4cd63cad4e3641ca79a5242443211a1a82..37c3feb527d55a4ac60be92c4ed6919abccdbbc3 100644 (file)
@@ -766,6 +766,59 @@ static DWORD STDMETHODCALLTYPE buffer_GetPriority(IWineD3DBuffer *iface)
     return resource_get_priority((IWineD3DResource *)iface);
 }
 
+/* The caller provides a GL context */
+static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info)
+{
+        BYTE *map;
+        UINT start = 0, len = 0;
+
+        ENTER_GL();
+        GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
+        checkGLcall("glBindBufferARB");
+        if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
+        {
+            GLbitfield mapflags;
+            mapflags = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
+            map = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0,
+                                              This->resource.size, mapflags));
+            checkGLcall("glMapBufferRange");
+        }
+        else
+        {
+            map = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_WRITE_ONLY_ARB));
+            checkGLcall("glMapBufferARB");
+        }
+        if (!map)
+        {
+            LEAVE_GL();
+            ERR("Failed to map opengl buffer\n");
+            return;
+        }
+
+        while(This->modified_areas)
+        {
+            This->modified_areas--;
+            start = This->maps[This->modified_areas].offset;
+            len = This->maps[This->modified_areas].size;
+
+            memcpy(map + start, This->resource.allocatedMemory + start, len);
+
+            if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
+            {
+                GL_EXTCALL(glFlushMappedBufferRange(This->buffer_type_hint, start, len));
+                checkGLcall("glFlushMappedBufferRange");
+            }
+            else if (This->flags & WINED3D_BUFFER_FLUSH)
+            {
+                GL_EXTCALL(glFlushMappedBufferRangeAPPLE(This->buffer_type_hint, start, len));
+                checkGLcall("glFlushMappedBufferRangeAPPLE");
+            }
+        }
+        GL_EXTCALL(glUnmapBufferARB(This->buffer_type_hint));
+        checkGLcall("glUnmapBufferARB");
+        LEAVE_GL();
+}
+
 static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface)
 {
     struct wined3d_buffer *This = (struct wined3d_buffer *)iface;
@@ -896,18 +949,7 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface)
             return;
         }
 
-        ENTER_GL();
-        GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
-        checkGLcall("glBindBufferARB");
-        while(This->modified_areas)
-        {
-            This->modified_areas--;
-            start = This->maps[This->modified_areas].offset;
-            len = This->maps[This->modified_areas].size;
-            GL_EXTCALL(glBufferSubDataARB(This->buffer_type_hint, start, len, This->resource.allocatedMemory + start));
-            checkGLcall("glBufferSubDataARB");
-        }
-        LEAVE_GL();
+        buffer_direct_upload(This, context->gl_info);
 
         context_release(context);
         return;