Module: wine Branch: master Commit: 6c53871d302cdd257675b88a01a7b6fc4944b06e URL: http://source.winehq.org/git/wine.git/?a=commit;h=6c53871d302cdd257675b88a01...
Author: Stefan Dösinger stefan@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 {