wined3d: Implement NOOVERWRITE and DISCARD volume maps.

This commit is contained in:
Stefan Dösinger 2013-08-26 02:01:28 +02:00 committed by Alexandre Julliard
parent 8c708486c3
commit bd866c0294
4 changed files with 85 additions and 61 deletions

View File

@ -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");

View File

@ -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;
}

View File

@ -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);

View File

@ -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