From: Akihiro Sagawa Subject: [PATCH 3/4] wined3d: Update a part of the texture if dirty regions is tracked. Message-Id: <20191207191520.EB3B.375B48EC@gmail.com> Date: Sat, 07 Dec 2019 19:16:09 +0900 Wine-Bugs: https://bugs.winehq.org/show_bug.cgi?id=35205 Signed-off-by: Akihiro Sagawa --- dlls/d3d9/tests/visual.c | 12 ++++++------ dlls/wined3d/device.c | 49 +++++++++++++++++++++++++++++++++++++++++------- dlls/wined3d/texture.c | 11 ++++------- 3 files changed, 52 insertions(+), 20 deletions(-) diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index 0a9fb0a..c873370 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -19340,7 +19340,7 @@ static void add_dirty_rect_test(void) ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr); add_dirty_rect_test_draw(device); color = getPixelColor(device, 320, 240); - todo_wine ok(color_match(color, 0x00ff0000, 1), + ok(color_match(color, 0x00ff0000, 1), "Expected color 0x00ff0000, got 0x%08x.\n", color); hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); @@ -19353,7 +19353,7 @@ static void add_dirty_rect_test(void) ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr); add_dirty_rect_test_draw(device); color = getPixelColor(device, 320, 240); - todo_wine ok(color_match(color, 0x00ff0000, 1), + ok(color_match(color, 0x00ff0000, 1), "Expected color 0x00ff0000, got 0x%08x.\n", color); hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); @@ -19365,7 +19365,7 @@ static void add_dirty_rect_test(void) ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr); add_dirty_rect_test_draw(device); color = getPixelColor(device, 320, 240); - todo_wine ok(color_match(color, 0x00ff0000, 1), + ok(color_match(color, 0x00ff0000, 1), "Expected color 0x00ff0000, got 0x%08x.\n", color); hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); @@ -19382,7 +19382,7 @@ static void add_dirty_rect_test(void) ok(color_match(color, 0x0000ff00, 1), "Expected color 0x0000ff00, got 0x%08x.\n", color); color = getPixelColor(device, 1, 1); - todo_wine ok(color_match(color, 0x00ff0000, 1), + ok(color_match(color, 0x00ff0000, 1), "Expected color 0x00ff0000, got 0x%08x.\n", color); hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); @@ -19404,7 +19404,7 @@ static void add_dirty_rect_test(void) ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr); add_dirty_rect_test_draw(device); color = getPixelColor(device, 320, 240); - todo_wine ok(color_match(color, 0x0000ff00, 1), + ok(color_match(color, 0x0000ff00, 1), "Expected color 0x0000ff00, got 0x%08x.\n", color); hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); @@ -19416,7 +19416,7 @@ static void add_dirty_rect_test(void) ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr); add_dirty_rect_test_draw(device); color = getPixelColor(device, 320, 240); - todo_wine ok(color_match(color, 0x0000ff00, 1), + ok(color_match(color, 0x0000ff00, 1), "Expected color 0x0000ff00, got 0x%08x.\n", color); hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 9337ac1..7705a83 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4062,6 +4062,7 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, unsigned int layer_count, level_count, i, j; enum wined3d_resource_type type; struct wined3d_box box; + BOOL entire_texture = TRUE; TRACE("device %p, src_texture %p, dst_texture %p.\n", device, src_texture, dst_texture); @@ -4127,16 +4128,50 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, return WINED3DERR_INVALIDCALL; } + if (src_texture->dirty_regions) + for (i = 0; i < layer_count && entire_texture; ++i) + if (src_texture->dirty_regions[i].count < MAX_DIRTY_REGION_COUNT) + entire_texture = FALSE; + /* Update every surface level of the texture. */ - for (i = 0; i < level_count; ++i) + if (entire_texture) { - wined3d_texture_get_level_box(dst_texture, i, &box); - for (j = 0; j < layer_count; ++j) + for (i = 0; i < level_count; ++i) + { + wined3d_texture_get_level_box(dst_texture, i, &box); + for (j = 0; j < layer_count; ++j) + { + wined3d_cs_emit_blt_sub_resource(device->cs, + &dst_texture->resource, j * dst_level_count + i, &box, + &src_texture->resource, j * src_level_count + i + src_skip_levels, &box, + 0, NULL, WINED3D_TEXF_POINT); + } + } + } + else + { + for (i = 0; i < layer_count; ++i) { - wined3d_cs_emit_blt_sub_resource(device->cs, - &dst_texture->resource, j * dst_level_count + i, &box, - &src_texture->resource, j * src_level_count + i + src_skip_levels, &box, - 0, NULL, WINED3D_TEXF_POINT); + for (j = 0; j < level_count; ++j) + { + /* TODO: We could pass an array of boxes here to avoid + multiple context acquisitions for the same resource. */ + unsigned int k, src_level = j + src_skip_levels; + for (k = 0; k < src_texture->dirty_regions[i].count; ++k) + { + box = src_texture->dirty_regions[i].box[k]; + if (src_level) + wined3d_box_set(&box, box.left >> src_level, box.top >> src_level, + (box.right + (1u << src_level) - 1) >> src_level, + (box.bottom + (1u << src_level) - 1) >> src_level, + box.front >> src_level, + (box.back + (1u << src_level) - 1) >> src_level); + wined3d_cs_emit_blt_sub_resource(device->cs, + &dst_texture->resource, i * dst_level_count + j, &box, + &src_texture->resource, i * src_level_count + src_level, &box, + 0, NULL, WINED3D_TEXF_POINT); + } + } } } diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 1882352..852b934 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -1831,14 +1831,11 @@ 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);