From bd866c02949890ca77c7058a00562fbd16375533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Mon, 26 Aug 2013 02:01:28 +0200 Subject: [PATCH] wined3d: Implement NOOVERWRITE and DISCARD volume maps. --- dlls/wined3d/buffer.c | 54 ++-------------------------------- dlls/wined3d/resource.c | 50 +++++++++++++++++++++++++++++++ dlls/wined3d/volume.c | 39 ++++++++++++++++++------ dlls/wined3d/wined3d_private.h | 3 ++ 4 files changed, 85 insertions(+), 61 deletions(-) diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index b3f760b6b9a..81786043ea2 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -922,56 +922,6 @@ void CDECL wined3d_buffer_preload(struct wined3d_buffer *buffer) context_release(context); } -static DWORD buffer_sanitize_flags(const struct wined3d_buffer *buffer, DWORD flags) -{ - /* Not all flags make sense together, but Windows never returns an error. - * Catch the cases that could cause issues. */ - if (flags & WINED3D_MAP_READONLY) - { - if (flags & WINED3D_MAP_DISCARD) - { - WARN("WINED3D_MAP_READONLY combined with WINED3D_MAP_DISCARD, ignoring flags.\n"); - return 0; - } - if (flags & WINED3D_MAP_NOOVERWRITE) - { - WARN("WINED3D_MAP_READONLY combined with WINED3D_MAP_NOOVERWRITE, ignoring flags.\n"); - return 0; - } - } - else if ((flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)) - == (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)) - { - WARN("WINED3D_MAP_DISCARD and WINED3D_MAP_NOOVERWRITE used together, ignoring.\n"); - return 0; - } - else if (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE) - && !(buffer->resource.usage & WINED3DUSAGE_DYNAMIC)) - { - WARN("DISCARD or NOOVERWRITE map on non-dynamic buffer, ignoring.\n"); - return 0; - } - - return flags; -} - -static GLbitfield buffer_gl_map_flags(DWORD d3d_flags) -{ - GLbitfield ret = 0; - - if (!(d3d_flags & WINED3D_MAP_READONLY)) - ret |= GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT; - if (!(d3d_flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))) - ret |= GL_MAP_READ_BIT; - - if (d3d_flags & WINED3D_MAP_DISCARD) - ret |= GL_MAP_INVALIDATE_BUFFER_BIT; - if (d3d_flags & WINED3D_MAP_NOOVERWRITE) - ret |= GL_MAP_UNSYNCHRONIZED_BIT; - - return ret; -} - struct wined3d_resource * CDECL wined3d_buffer_get_resource(struct wined3d_buffer *buffer) { TRACE("buffer %p.\n", buffer); @@ -986,7 +936,7 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN TRACE("buffer %p, offset %u, size %u, data %p, flags %#x\n", buffer, offset, size, data, flags); - flags = buffer_sanitize_flags(buffer, flags); + flags = wined3d_resource_sanitize_map_flags(&buffer->resource, flags); count = ++buffer->resource.map_count; if (buffer->buffer_object) @@ -1017,7 +967,7 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) { - GLbitfield mapflags = buffer_gl_map_flags(flags); + GLbitfield mapflags = wined3d_resource_gl_map_flags(flags); buffer->resource.allocatedMemory = GL_EXTCALL(glMapBufferRange(buffer->buffer_type_hint, 0, buffer->resource.size, mapflags)); checkGLcall("glMapBufferRange"); diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c index 59fced9a80f..ca322b27b61 100644 --- a/dlls/wined3d/resource.c +++ b/dlls/wined3d/resource.c @@ -358,3 +358,53 @@ void wined3d_resource_free_sysmem(void *mem) HeapFree(GetProcessHeap(), 0, *(--p)); } + +DWORD wined3d_resource_sanitize_map_flags(const struct wined3d_resource *resource, DWORD flags) +{ + /* Not all flags make sense together, but Windows never returns an error. + * Catch the cases that could cause issues. */ + if (flags & WINED3D_MAP_READONLY) + { + if (flags & WINED3D_MAP_DISCARD) + { + WARN("WINED3D_MAP_READONLY combined with WINED3D_MAP_DISCARD, ignoring flags.\n"); + return 0; + } + if (flags & WINED3D_MAP_NOOVERWRITE) + { + WARN("WINED3D_MAP_READONLY combined with WINED3D_MAP_NOOVERWRITE, ignoring flags.\n"); + return 0; + } + } + else if ((flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)) + == (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)) + { + WARN("WINED3D_MAP_DISCARD and WINED3D_MAP_NOOVERWRITE used together, ignoring.\n"); + return 0; + } + else if (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE) + && !(resource->usage & WINED3DUSAGE_DYNAMIC)) + { + WARN("DISCARD or NOOVERWRITE map on non-dynamic buffer, ignoring.\n"); + return 0; + } + + return flags; +} + +GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags) +{ + GLbitfield ret = 0; + + if (!(d3d_flags & WINED3D_MAP_READONLY)) + ret |= GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT; + if (!(d3d_flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))) + ret |= GL_MAP_READ_BIT; + + if (d3d_flags & WINED3D_MAP_DISCARD) + ret |= GL_MAP_INVALIDATE_BUFFER_BIT; + if (d3d_flags & WINED3D_MAP_NOOVERWRITE) + ret |= GL_MAP_UNSYNCHRONIZED_BIT; + + return ret; +} diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c index 3f1563c8b05..1813a316c45 100644 --- a/dlls/wined3d/volume.c +++ b/dlls/wined3d/volume.c @@ -469,6 +469,7 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, map_desc->data = NULL; return WINED3DERR_INVALIDCALL; } + flags = wined3d_resource_sanitize_map_flags(&volume->resource, flags); if (volume->flags & WINED3D_VFLAG_PBO) { @@ -476,10 +477,25 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, gl_info = context->gl_info; wined3d_volume_prepare_pbo(volume, context); - wined3d_volume_load_location(volume, context, WINED3D_LOCATION_BUFFER); + if (flags & WINED3D_MAP_DISCARD) + wined3d_volume_validate_location(volume, WINED3D_LOCATION_BUFFER); + else + wined3d_volume_load_location(volume, context, WINED3D_LOCATION_BUFFER); GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->pbo)); - base_memory = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); + + if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) + { + GLbitfield mapflags = wined3d_resource_gl_map_flags(flags); + mapflags &= ~GL_MAP_FLUSH_EXPLICIT_BIT; + base_memory = GL_EXTCALL(glMapBufferRange(GL_PIXEL_UNPACK_BUFFER_ARB, + 0, volume->resource.size, mapflags)); + } + else + { + base_memory = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); + } + GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); checkGLcall("Map PBO"); @@ -487,14 +503,19 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, } else { - if (!(volume->locations & WINED3D_LOCATION_SYSMEM)) + if (!volume_prepare_system_memory(volume)) + { + WARN("Out of memory.\n"); + map_desc->data = NULL; + return E_OUTOFMEMORY; + } + + if (flags & WINED3D_MAP_DISCARD) + { + wined3d_volume_validate_location(volume, WINED3D_LOCATION_SYSMEM); + } + else if (!(volume->locations & WINED3D_LOCATION_SYSMEM)) { - if (!volume_prepare_system_memory(volume)) - { - WARN("Out of memory.\n"); - map_desc->data = NULL; - return E_OUTOFMEMORY; - } context = context_acquire(device, NULL); wined3d_volume_load_location(volume, context, WINED3D_LOCATION_SYSMEM); context_release(context); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 1773ba77ff6..4db76000789 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1968,6 +1968,9 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device * const struct wined3d_resource_ops *resource_ops) DECLSPEC_HIDDEN; DWORD resource_set_priority(struct wined3d_resource *resource, DWORD priority) DECLSPEC_HIDDEN; void resource_unload(struct wined3d_resource *resource) DECLSPEC_HIDDEN; +DWORD wined3d_resource_sanitize_map_flags(const struct wined3d_resource *resource, + DWORD flags) DECLSPEC_HIDDEN; +GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags) DECLSPEC_HIDDEN; /* Tests show that the start address of resources is 32 byte aligned */ #define RESOURCE_ALIGNMENT 16