From 3b96ac290db1bca225ecfff4581e0969202007ad Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Wed, 20 Apr 2016 19:29:12 +0200 Subject: [PATCH] wined3d: Allocate system memory for complete textures. Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/d3d8/tests/device.c | 4 +-- dlls/d3d9/tests/device.c | 4 +-- dlls/wined3d/surface.c | 21 +++++------- dlls/wined3d/swapchain.c | 6 ++-- dlls/wined3d/texture.c | 60 ++++++++++++++++++++++++---------- dlls/wined3d/volume.c | 22 +++++-------- dlls/wined3d/wined3d_private.h | 2 ++ 7 files changed, 69 insertions(+), 50 deletions(-) diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c index 13fe51ac62d..11969f46576 100644 --- a/dlls/d3d8/tests/device.c +++ b/dlls/d3d8/tests/device.c @@ -7929,7 +7929,7 @@ static void test_miptree_layout(void) if (!i) base = map_desc.pBits; else - todo_wine ok(map_desc.pBits == base + offset, + ok(map_desc.pBits == base + offset, "%s, %s, level %u: Got unexpected pBits %p, expected %p.\n", pools[pool_idx].name, formats[format_idx].name, i, map_desc.pBits, base + offset); offset += (base_dimension >> i) * map_desc.Pitch; @@ -7968,7 +7968,7 @@ static void test_miptree_layout(void) if (!i && !j) base = map_desc.pBits; else - todo_wine ok(map_desc.pBits == base + offset, + ok(map_desc.pBits == base + offset, "%s, %s, face %u, level %u: Got unexpected pBits %p, expected %p.\n", pools[pool_idx].name, formats[format_idx].name, i, j, map_desc.pBits, base + offset); offset += (base_dimension >> j) * map_desc.Pitch; diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index 8fc9a22c472..8860bce3928 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -11060,7 +11060,7 @@ static void test_miptree_layout(void) if (!i) base = map_desc.pBits; else - todo_wine ok(map_desc.pBits == base + offset, + ok(map_desc.pBits == base + offset, "%s, %s, level %u: Got unexpected pBits %p, expected %p.\n", pools[pool_idx].name, formats[format_idx].name, i, map_desc.pBits, base + offset); offset += (base_dimension >> i) * map_desc.Pitch; @@ -11099,7 +11099,7 @@ static void test_miptree_layout(void) if (!i && !j) base = map_desc.pBits; else - todo_wine ok(map_desc.pBits == base + offset, + ok(map_desc.pBits == base + offset, "%s, %s, face %u, level %u: Got unexpected pBits %p, expected %p.\n", pools[pool_idx].name, formats[format_idx].name, i, j, map_desc.pBits, base + offset); offset += (base_dimension >> j) * map_desc.Pitch; diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 075de5fddd3..44d442bebea 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -398,7 +398,7 @@ HRESULT wined3d_surface_create_dc(struct wined3d_surface *surface) } wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding); - desc.pMemory = wined3d_texture_map_bo_address(&data, surface->resource.size, + desc.pMemory = wined3d_texture_map_bo_address(&data, texture->sub_resources[sub_resource_idx].size, gl_info, GL_PIXEL_UNPACK_BUFFER, 0); if (context) @@ -2746,21 +2746,21 @@ static void surface_copy_simple_location(struct wined3d_surface *surface, DWORD unsigned int sub_resource_idx = surface_get_sub_resource_idx(surface); struct wined3d_texture *texture = surface->container; struct wined3d_device *device = texture->resource.device; + struct wined3d_texture_sub_resource *sub_resource; struct wined3d_context *context; const struct wined3d_gl_info *gl_info; struct wined3d_bo_address dst, src; - UINT size = surface->resource.size; + sub_resource = &texture->sub_resources[sub_resource_idx]; wined3d_texture_get_memory(texture, sub_resource_idx, &dst, location); - wined3d_texture_get_memory(texture, sub_resource_idx, &src, - texture->sub_resources[sub_resource_idx].locations); + wined3d_texture_get_memory(texture, sub_resource_idx, &src, sub_resource->locations); if (dst.buffer_object) { context = context_acquire(device, NULL); gl_info = context->gl_info; GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, dst.buffer_object)); - GL_EXTCALL(glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, size, src.addr)); + GL_EXTCALL(glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, sub_resource->size, src.addr)); GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); checkGLcall("Upload PBO"); context_release(context); @@ -2771,13 +2771,13 @@ static void surface_copy_simple_location(struct wined3d_surface *surface, DWORD context = context_acquire(device, NULL); gl_info = context->gl_info; GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, src.buffer_object)); - GL_EXTCALL(glGetBufferSubData(GL_PIXEL_PACK_BUFFER, 0, size, dst.addr)); + GL_EXTCALL(glGetBufferSubData(GL_PIXEL_PACK_BUFFER, 0, sub_resource->size, dst.addr)); GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0)); checkGLcall("Download PBO"); context_release(context); return; } - memcpy(dst.addr, src.addr, size); + memcpy(dst.addr, src.addr, sub_resource->size); } /* Context activation is done by the caller. */ @@ -4316,16 +4316,11 @@ HRESULT wined3d_surface_init(struct wined3d_surface *surface, struct wined3d_tex const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; const struct wined3d_format *format = wined3d_get_format(gl_info, desc->format); UINT multisample_quality = desc->multisample_quality; - unsigned int resource_size; HRESULT hr; - resource_size = wined3d_format_calculate_size(format, device->surface_alignment, desc->width, desc->height, 1); - if (!resource_size) - return WINED3DERR_INVALIDCALL; - if (FAILED(hr = resource_init(&surface->resource, device, WINED3D_RTYPE_SURFACE, format, desc->multisample_type, multisample_quality, desc->usage, desc->pool, desc->width, desc->height, - 1, resource_size, NULL, &wined3d_null_parent_ops, &surface_resource_ops))) + 1, 0, NULL, &wined3d_null_parent_ops, &surface_resource_ops))) { WARN("Failed to initialize resource, returning %#x.\n", hr); return hr; diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 202a890b1c5..f982add3fc3 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -703,15 +703,15 @@ static void swapchain_gdi_present(struct wined3d_swapchain *swapchain, /* Flip the surface data. */ dc = front->dc; bitmap = front->bitmap; - data = front->resource.heap_memory; + data = front->container->resource.heap_memory; front->dc = back->dc; front->bitmap = back->bitmap; - front->resource.heap_memory = back->resource.heap_memory; + front->container->resource.heap_memory = back->container->resource.heap_memory; back->dc = dc; back->bitmap = bitmap; - back->resource.heap_memory = data; + back->container->resource.heap_memory = data; /* FPS support */ if (TRACE_ON(fps)) diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 047e12df0a3..2d92c8313eb 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -93,8 +93,8 @@ static void wined3d_texture_evict_sysmem(struct wined3d_texture *texture) ERR("WINED3D_LOCATION_SYSMEM is the only location for sub-resource %u of texture %p.\n", i, texture); sub_resource->locations &= ~WINED3D_LOCATION_SYSMEM; - wined3d_resource_free_sysmem(sub_resource->resource); } + wined3d_resource_free_sysmem(&texture->resource); } void wined3d_texture_validate_location(struct wined3d_texture *texture, @@ -203,7 +203,8 @@ void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int su } if (locations & WINED3D_LOCATION_SYSMEM) { - data->addr = sub_resource->resource->heap_memory; + data->addr = texture->resource.heap_memory; + data->addr += sub_resource->offset; data->buffer_object = 0; return; } @@ -219,6 +220,7 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc const struct wined3d_resource_ops *resource_ops) { const struct wined3d_format *format = wined3d_get_format(&device->adapter->gl_info, desc->format); + unsigned int i, j, size, offset = 0; HRESULT hr; TRACE("texture %p, texture_ops %p, layer_count %u, level_count %u, resource_type %s, format %s, " @@ -229,9 +231,30 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc debug_d3dusage(desc->usage), debug_d3dpool(desc->pool), desc->width, desc->height, desc->depth, flags, device, parent, parent_ops, resource_ops); + if (!desc->width || !desc->height || !desc->depth) + return WINED3DERR_INVALIDCALL; + + for (i = 0; i < layer_count; ++i) + { + for (j = 0; j < level_count; ++j) + { + unsigned int idx = i * level_count + j; + + size = wined3d_format_calculate_size(format, device->surface_alignment, + max(1, desc->width >> j), max(1, desc->height >> j), max(1, desc->depth >> j)); + texture->sub_resources[idx].offset = offset; + texture->sub_resources[idx].size = size; + offset += size; + } + offset = (offset + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1); + } + + if (!offset) + return WINED3DERR_INVALIDCALL; + if (FAILED(hr = resource_init(&texture->resource, device, desc->resource_type, format, desc->multisample_type, desc->multisample_quality, desc->usage, desc->pool, - desc->width, desc->height, desc->depth, 0, parent, parent_ops, resource_ops))) + desc->width, desc->height, desc->depth, offset, parent, parent_ops, resource_ops))) { static unsigned int once; @@ -984,7 +1007,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT create_dib = TRUE; } - wined3d_resource_free_sysmem(sub_resource->resource); + wined3d_resource_free_sysmem(&texture->resource); if ((texture->row_pitch = pitch)) texture->slice_pitch = height * pitch; @@ -998,13 +1021,14 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT texture->resource.multisample_quality = multisample_quality; texture->resource.width = width; texture->resource.height = height; + texture->resource.size = texture->slice_pitch; sub_resource->resource->format = format; sub_resource->resource->multisample_type = multisample_type; sub_resource->resource->multisample_quality = multisample_quality; sub_resource->resource->width = width; sub_resource->resource->height = height; - sub_resource->resource->size = texture->slice_pitch; + sub_resource->size = texture->slice_pitch; sub_resource->locations = WINED3D_LOCATION_DISCARDED; if (((width & (width - 1)) || (height & (height - 1))) && !gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] @@ -1055,21 +1079,20 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT static void wined3d_texture_prepare_buffer_object(struct wined3d_texture *texture, unsigned int sub_resource_idx, const struct wined3d_gl_info *gl_info) { - GLuint *buffer_object; + struct wined3d_texture_sub_resource *sub_resource; - buffer_object = &texture->sub_resources[sub_resource_idx].buffer_object; - if (*buffer_object) + sub_resource = &texture->sub_resources[sub_resource_idx]; + if (sub_resource->buffer_object) return; - GL_EXTCALL(glGenBuffers(1, buffer_object)); - GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, *buffer_object)); - GL_EXTCALL(glBufferData(GL_PIXEL_UNPACK_BUFFER, - texture->sub_resources[sub_resource_idx].resource->size, NULL, GL_STREAM_DRAW)); + GL_EXTCALL(glGenBuffers(1, &sub_resource->buffer_object)); + GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, sub_resource->buffer_object)); + GL_EXTCALL(glBufferData(GL_PIXEL_UNPACK_BUFFER, sub_resource->size, NULL, GL_STREAM_DRAW)); GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); checkGLcall("Create buffer object"); TRACE("Created buffer object %u for texture %p, sub-resource %u.\n", - *buffer_object, texture, sub_resource_idx); + sub_resource->buffer_object, texture, sub_resource_idx); } static void wined3d_texture_force_reload(struct wined3d_texture *texture) @@ -1179,10 +1202,10 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned switch (location) { case WINED3D_LOCATION_SYSMEM: - if (texture->sub_resources[sub_resource_idx].resource->heap_memory) + if (texture->resource.heap_memory) return TRUE; - if (!wined3d_resource_allocate_sysmem(texture->sub_resources[sub_resource_idx].resource)) + if (!wined3d_resource_allocate_sysmem(&texture->resource)) { ERR("Failed to allocate system memory.\n"); return FALSE; @@ -1589,7 +1612,7 @@ static HRESULT texture_resource_sub_resource_map(struct wined3d_resource *resour wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding); wined3d_texture_get_memory(texture, sub_resource_idx, &data, texture->resource.map_binding); - base_memory = wined3d_texture_map_bo_address(&data, sub_resource->resource->size, + base_memory = wined3d_texture_map_bo_address(&data, sub_resource->size, gl_info, GL_PIXEL_UNPACK_BUFFER, flags); TRACE("Base memory pointer %p.\n", base_memory); @@ -2128,7 +2151,10 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct texture->target = GL_TEXTURE_3D; if (wined3d_texture_use_pbo(texture, gl_info)) + { + wined3d_resource_free_sysmem(&texture->resource); texture->resource.map_binding = WINED3D_LOCATION_BUFFER; + } if (!(volumes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*volumes) * levels))) { @@ -2391,7 +2417,7 @@ HRESULT CDECL wined3d_texture_get_sub_resource_desc(const struct wined3d_texture desc->width = wined3d_texture_get_level_width(texture, level_idx); desc->height = wined3d_texture_get_level_height(texture, level_idx); desc->depth = wined3d_texture_get_level_depth(texture, level_idx); - desc->size = texture->sub_resources[sub_resource_idx].resource->size; + desc->size = texture->sub_resources[sub_resource_idx].size; return WINED3D_OK; } diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c index 6a922119c08..41a45f18465 100644 --- a/dlls/wined3d/volume.c +++ b/dlls/wined3d/volume.c @@ -146,6 +146,7 @@ static DWORD volume_access_from_location(DWORD location) static void wined3d_volume_srgb_transfer(struct wined3d_volume *volume, struct wined3d_context *context, BOOL dest_is_srgb) { + struct wined3d_texture *texture = volume->container; struct wined3d_bo_address data; /* Optimizations are possible, but the effort should be put into either * implementing EXT_SRGB_DECODE in the driver or finding out why we @@ -156,13 +157,12 @@ static void wined3d_volume_srgb_transfer(struct wined3d_volume *volume, WARN_(d3d_perf)("Performing slow rgb/srgb volume transfer.\n"); data.buffer_object = 0; - data.addr = HeapAlloc(GetProcessHeap(), 0, volume->resource.size); - if (!data.addr) + if (!(data.addr = HeapAlloc(GetProcessHeap(), 0, texture->sub_resources[volume->texture_level].size))) return; - wined3d_texture_bind_and_dirtify(volume->container, context, !dest_is_srgb); + wined3d_texture_bind_and_dirtify(texture, context, !dest_is_srgb); wined3d_volume_download_data(volume, context, &data); - wined3d_texture_bind_and_dirtify(volume->container, context, dest_is_srgb); + wined3d_texture_bind_and_dirtify(texture, context, dest_is_srgb); wined3d_volume_upload_data(volume, context, wined3d_const_bo_address(&data)); HeapFree(GetProcessHeap(), 0, data.addr); @@ -211,7 +211,8 @@ BOOL wined3d_volume_load_location(struct wined3d_volume *volume, case WINED3D_LOCATION_TEXTURE_SRGB: if (sub_resource->locations & WINED3D_LOCATION_SYSMEM) { - struct wined3d_const_bo_address data = {0, volume->resource.heap_memory}; + struct wined3d_const_bo_address data = {0, texture->resource.heap_memory}; + data.addr += sub_resource->offset; wined3d_texture_bind_and_dirtify(texture, context, location == WINED3D_LOCATION_TEXTURE_SRGB); wined3d_volume_upload_data(volume, context, &data); @@ -241,8 +242,9 @@ BOOL wined3d_volume_load_location(struct wined3d_volume *volume, case WINED3D_LOCATION_SYSMEM: if (sub_resource->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) { - struct wined3d_bo_address data = {0, volume->resource.heap_memory}; + struct wined3d_bo_address data = {0, texture->resource.heap_memory}; + data.addr += sub_resource->offset; if (sub_resource->locations & WINED3D_LOCATION_TEXTURE_RGB) wined3d_texture_bind_and_dirtify(texture, context, FALSE); else @@ -348,21 +350,15 @@ HRESULT wined3d_volume_init(struct wined3d_volume *volume, struct wined3d_textur const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; const struct wined3d_format *format = wined3d_get_format(gl_info, desc->format); HRESULT hr; - UINT size; - - size = wined3d_format_calculate_size(format, device->surface_alignment, desc->width, desc->height, desc->depth); if (FAILED(hr = resource_init(&volume->resource, device, WINED3D_RTYPE_VOLUME, format, WINED3D_MULTISAMPLE_NONE, 0, desc->usage, desc->pool, desc->width, desc->height, desc->depth, - size, NULL, &wined3d_null_parent_ops, &volume_resource_ops))) + 0, NULL, &wined3d_null_parent_ops, &volume_resource_ops))) { WARN("Failed to initialize resource, returning %#x.\n", hr); return hr; } - if (container->resource.map_binding == WINED3D_LOCATION_BUFFER) - wined3d_resource_free_sysmem(&volume->resource); - volume->texture_level = level; volume->container = container; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 4f06796091e..2118a144e69 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2505,6 +2505,8 @@ struct wined3d_texture struct wined3d_surface *surface; struct wined3d_volume *volume; } u; + unsigned int offset; + unsigned int size; unsigned int map_count; DWORD locations;