From: Akihiro Sagawa Subject: [PATCH 2/4] wined3d: Record texture dirty regions. Message-Id: <20191207191516.EB37.375B48EC@gmail.com> Date: Sat, 07 Dec 2019 19:16:07 +0900 Signed-off-by: Akihiro Sagawa --- dlls/wined3d/device.c | 2 ++ dlls/wined3d/texture.c | 66 ++++++++++++++++++++++++++++++++++++++++++ dlls/wined3d/wined3d_private.h | 3 ++ 3 files changed, 71 insertions(+) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 0ae841d..9337ac1 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4140,6 +4140,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 e13d46c..1882352 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -340,6 +340,15 @@ 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) + for (i = 0; i < texture->layer_count; ++i) + texture->dirty_regions[i].count = 0; +} + static BOOL wined3d_texture_copy_sysmem_location(struct wined3d_texture *texture, unsigned int sub_resource_idx, struct wined3d_context *context, DWORD location) { @@ -1099,7 +1108,11 @@ static void wined3d_texture_destroy_object(void *object) } if (texture->dirty_regions) + { + for (i = 0; i < texture->layer_count; ++i) + heap_free(texture->dirty_regions[i].box); heap_free(texture->dirty_regions); + } if (texture->overlay_info) { @@ -1773,6 +1786,40 @@ 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, UINT layer, const struct wined3d_box *box) +{ + if (!texture->dirty_regions) + return; + if (texture->dirty_regions[layer].count == MAX_DIRTY_REGION_COUNT) + return; + + if (!box || (!box->left && !box->top && !box->front + && box->right == texture->resource.width + && box->bottom == texture->resource.height + && box->back == texture->resource.depth)) + texture->dirty_regions[layer].count = MAX_DIRTY_REGION_COUNT; + else + { + SIZE_T count = texture->dirty_regions[layer].count + 1; + if (count >= MAX_DIRTY_REGION_COUNT + || !wined3d_array_reserve((void **)&texture->dirty_regions[layer].box, + &texture->dirty_regions[layer].size, + count, sizeof(struct wined3d_box))) + { + TRACE("dirty_region[%u].count = MAX_DIRTY_REIGON_COUNT\n", layer); + texture->dirty_regions[layer].count = MAX_DIRTY_REGION_COUNT; + } + else + { + TRACE("dirty_region[%u].count=%u, size=%u\n", layer, + texture->dirty_regions[layer].count, + (unsigned int)texture->dirty_regions[layer].size); + texture->dirty_regions[layer].box[texture->dirty_regions[layer].count] = *box; + texture->dirty_regions[layer].count = count; + } + } +} + HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture, UINT layer, const struct wined3d_box *dirty_region) { @@ -1794,6 +1841,7 @@ HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture, FIXME("Ignoring dirty_region %s.\n", debug_box(dirty_region)); } + 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; @@ -3093,6 +3141,24 @@ static HRESULT texture_resource_sub_resource_map(struct wined3d_resource *resour return E_OUTOFMEMORY; } + if (flags & WINED3D_MAP_WRITE && !(flags & WINED3D_MAP_NO_DIRTY_UPDATE) + && texture->dirty_regions && !texture_level) + { + /* We only record dirty regions for the top most level texture. */ + unsigned int layer = sub_resource_idx / texture->level_count; + if (!box) + wined3d_texture_dirty_region_add(texture, layer, NULL); + else + { + struct wined3d_box b; + wined3d_box_set(&b, box->left, box->top, + min(texture->resource.width, box->right), + min(texture->resource.height, box->bottom), + box->front, min(texture->resource.depth, box->back)); + wined3d_texture_dirty_region_add(texture, layer, &b); + } + } + 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); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 4f5a001..665663b 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3503,6 +3503,8 @@ struct wined3d_texture_ops #define WINED3D_TEXTURE_ASYNC_COLOR_KEY 0x00000001 +#define MAX_DIRTY_REGION_COUNT 7 + struct wined3d_texture { struct wined3d_resource resource; @@ -3673,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,