From: Akihiro Sagawa sagawa.aki@gmail.com
Signed-off-by: Akihiro Sagawa sagawa.aki@gmail.com Signed-off-by: Henri Verbeet hverbeet@codeweavers.com --- This supersedes patches 175193 and 175194.
dlls/d3d9/texture.c | 9 ++++- dlls/wined3d/device.c | 19 ++++++++++ dlls/wined3d/texture.c | 78 ++++++++++++++++++++++++++++++++++++++---- dlls/wined3d/wined3d_private.h | 10 ++++++ include/wine/wined3d.h | 1 + 5 files changed, 109 insertions(+), 8 deletions(-)
diff --git a/dlls/d3d9/texture.c b/dlls/d3d9/texture.c index ae754b5fa2c..2ef27a6de3d 100644 --- a/dlls/d3d9/texture.c +++ b/dlls/d3d9/texture.c @@ -1369,6 +1369,8 @@ HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device, } if (!levels) levels = wined3d_log2i(max(width, height)) + 1; + if (pool == D3DPOOL_SYSTEMMEM) + flags |= WINED3D_TEXTURE_CREATE_RECORD_DIRTY_REGIONS;
wined3d_mutex_lock(); hr = wined3d_texture_create(device->wined3d_device, &desc, 1, levels, flags, @@ -1449,6 +1451,8 @@ HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *devic } if (!levels) levels = wined3d_log2i(edge_length) + 1; + if (pool == D3DPOOL_SYSTEMMEM) + flags |= WINED3D_TEXTURE_CREATE_RECORD_DIRTY_REGIONS;
wined3d_mutex_lock(); hr = wined3d_texture_create(device->wined3d_device, &desc, 6, levels, flags, @@ -1470,6 +1474,7 @@ HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *dev UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) { struct wined3d_resource_desc desc; + DWORD flags = 0; HRESULT hr;
if (pool == D3DPOOL_MANAGED && device->d3d_parent->extended) @@ -1513,9 +1518,11 @@ HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *dev } if (!levels) levels = wined3d_log2i(max(max(width, height), depth)) + 1; + if (pool == D3DPOOL_SYSTEMMEM) + flags |= WINED3D_TEXTURE_CREATE_RECORD_DIRTY_REGIONS;
wined3d_mutex_lock(); - hr = wined3d_texture_create(device->wined3d_device, &desc, 1, levels, 0, + hr = wined3d_texture_create(device->wined3d_device, &desc, 1, levels, flags, NULL, texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture); wined3d_mutex_unlock(); if (FAILED(hr)) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 0ae841d4e35..dc92d4f4b74 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4059,8 +4059,10 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, { unsigned int src_size, dst_size, src_skip_levels = 0; unsigned int src_level_count, dst_level_count; + const struct wined3d_dirty_regions *regions; unsigned int layer_count, level_count, i, j; enum wined3d_resource_type type; + BOOL entire_texture = TRUE; struct wined3d_box box;
TRACE("device %p, src_texture %p, dst_texture %p.\n", device, src_texture, dst_texture); @@ -4127,6 +4129,21 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, return WINED3DERR_INVALIDCALL; }
+ if ((regions = src_texture->dirty_regions)) + { + for (i = 0; i < layer_count && entire_texture; ++i) + { + if (regions[i].box_count >= WINED3D_MAX_DIRTY_REGION_COUNT) + continue; + + entire_texture = FALSE; + break; + } + } + + if (!entire_texture) + FIXME("Ignoring dirty regions.\n"); + /* Update every surface level of the texture. */ for (i = 0; i < level_count; ++i) { @@ -4140,6 +4157,8 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, } }
+ wined3d_texture_clear_dirty_regions(src_texture); + return WINED3D_OK; }
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 7c9c8298519..03372504bc6 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -340,6 +340,21 @@ void wined3d_texture_invalidate_location(struct wined3d_texture *texture, sub_resource_idx, texture); }
+void wined3d_texture_clear_dirty_regions(struct wined3d_texture *texture) +{ + unsigned int i; + + TRACE("texture %p\n", texture); + + if (!texture->dirty_regions) + return; + + for (i = 0; i < texture->layer_count; ++i) + { + texture->dirty_regions[i].box_count = 0; + } +} + static BOOL wined3d_texture_copy_sysmem_location(struct wined3d_texture *texture, unsigned int sub_resource_idx, struct wined3d_context *context, DWORD location) { @@ -1114,6 +1129,15 @@ static void wined3d_texture_destroy_object(void *object) heap_free(texture->overlay_info); }
+ if (texture->dirty_regions) + { + for (i = 0; i < texture->layer_count; ++i) + { + heap_free(texture->dirty_regions[i].boxes); + } + heap_free(texture->dirty_regions); + } + resource->resource_ops->resource_unload(resource); }
@@ -1770,6 +1794,37 @@ static struct wined3d_texture_sub_resource *wined3d_texture_get_sub_resource(str return &texture->sub_resources[sub_resource_idx]; }
+static void wined3d_texture_dirty_region_add(struct wined3d_texture *texture, + unsigned int layer, const struct wined3d_box *box) +{ + struct wined3d_dirty_regions *regions; + unsigned int count; + + if (!texture->dirty_regions) + return; + + regions = &texture->dirty_regions[layer]; + count = regions->box_count + 1; + if (count >= WINED3D_MAX_DIRTY_REGION_COUNT || !box + || (!box->left && !box->top && !box->front + && box->right == texture->resource.width + && box->bottom == texture->resource.height + && box->back == texture->resource.depth)) + { + regions->box_count = WINED3D_MAX_DIRTY_REGION_COUNT; + return; + } + + if (!wined3d_array_reserve((void **)®ions->boxes, ®ions->boxes_size, count, sizeof(*regions->boxes))) + { + WARN("Failed to grow boxes array, marking entire texture dirty.\n"); + regions->box_count = WINED3D_MAX_DIRTY_REGION_COUNT; + return; + } + + regions->boxes[regions->box_count++] = *box; +} + HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture, UINT layer, const struct wined3d_box *dirty_region) { @@ -1781,16 +1836,13 @@ HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture, return WINED3DERR_INVALIDCALL; }
- if (dirty_region) + if (dirty_region && FAILED(wined3d_texture_check_box_dimensions(texture, 0, dirty_region))) { - if (FAILED(wined3d_texture_check_box_dimensions(texture, 0, dirty_region))) - { - WARN("Invalid dirty_region %s specified.\n", debug_box(dirty_region)); - return WINED3DERR_INVALIDCALL; - } - FIXME("Ignoring dirty_region %s.\n", debug_box(dirty_region)); + WARN("Invalid dirty_region %s specified.\n", debug_box(dirty_region)); + return WINED3DERR_INVALIDCALL; }
+ wined3d_texture_dirty_region_add(texture, layer, dirty_region); wined3d_cs_emit_add_dirty_texture_region(texture->resource.device->cs, texture, layer);
return WINED3D_OK; @@ -3090,6 +3142,11 @@ static HRESULT texture_resource_sub_resource_map(struct wined3d_resource *resour return E_OUTOFMEMORY; }
+ /* We only record dirty regions for the top-most level. */ + if (texture->dirty_regions && flags & WINED3D_MAP_WRITE + && !(flags & WINED3D_MAP_NO_DIRTY_UPDATE) && !texture_level) + wined3d_texture_dirty_region_add(texture, sub_resource_idx / texture->level_count, box); + if (flags & WINED3D_MAP_WRITE && (!(flags & WINED3D_MAP_NO_DIRTY_UPDATE) || (resource->usage & WINED3DUSAGE_DYNAMIC))) wined3d_texture_invalidate_location(texture, sub_resource_idx, ~resource->map_binding); @@ -3382,6 +3439,13 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc texture->flags |= WINED3D_TEXTURE_GENERATE_MIPMAPS; }
+ if (flags & WINED3D_TEXTURE_CREATE_RECORD_DIRTY_REGIONS + && !(texture->dirty_regions = heap_calloc(texture->layer_count, sizeof(*texture->dirty_regions)))) + { + wined3d_texture_cleanup_sync(texture); + return E_OUTOFMEMORY; + } + /* Precalculated scaling for 'faked' non power of two texture coords. */ if (texture->resource.gl_type == WINED3D_GL_RES_TYPE_TEX_RECT) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 8f9ad1ce856..60ddf74a0ec 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -74,6 +74,8 @@ #define WINED3D_QUIRK_BROKEN_ARB_FOG 0x00000200 #define WINED3D_QUIRK_NO_INDEPENDENT_BIT_DEPTHS 0x00000400
+#define WINED3D_MAX_DIRTY_REGION_COUNT 7 + struct wined3d_fragment_pipe_ops; struct wined3d_adapter; struct wined3d_context; @@ -3538,6 +3540,13 @@ struct wined3d_texture DWORD color_key_flags; } async;
+ struct wined3d_dirty_regions + { + struct wined3d_box *boxes; + SIZE_T boxes_size; + unsigned int box_count; + } *dirty_regions; + struct wined3d_overlay_info { struct list entry; @@ -3666,6 +3675,7 @@ void wined3d_texture_upload_from_texture(struct wined3d_texture *dst_texture, un unsigned int src_sub_resource_idx, const struct wined3d_box *src_box) DECLSPEC_HIDDEN; void wined3d_texture_validate_location(struct wined3d_texture *texture, unsigned int sub_resource_idx, DWORD location) DECLSPEC_HIDDEN; +void wined3d_texture_clear_dirty_regions(struct wined3d_texture *texture) DECLSPEC_HIDDEN;
HRESULT wined3d_texture_no3d_init(struct wined3d_texture *texture_no3d, struct wined3d_device *device, const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count, diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 4b5d4e02f9b..db88e110327 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -1565,6 +1565,7 @@ enum wined3d_shader_type #define WINED3D_TEXTURE_CREATE_GET_DC_LENIENT 0x00000004 #define WINED3D_TEXTURE_CREATE_GET_DC 0x00000008 #define WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS 0x00000010 +#define WINED3D_TEXTURE_CREATE_RECORD_DIRTY_REGIONS 0x00000020
#define WINED3D_STANDARD_MULTISAMPLE_PATTERN 0xffffffff