From 54edd5b220116febe704ecef8b3fb86621793ebe Mon Sep 17 00:00:00 2001 From: Akihiro Sagawa Date: Tue, 10 Dec 2019 21:26:16 +0330 Subject: [PATCH] wined3d: Update a part of the texture if dirty regions are tracked. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=35205 Signed-off-by: Akihiro Sagawa Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/d3d9/tests/visual.c | 12 +++---- dlls/wined3d/device.c | 67 ++++++++++++++++++++++++++++++++++------ 2 files changed, 63 insertions(+), 16 deletions(-) diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index 0a9fb0acc29..c87337057ea 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 dc92d4f4b74..89134207243 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4141,19 +4141,66 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, } } - if (!entire_texture) - FIXME("Ignoring dirty regions.\n"); - /* 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_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); + 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 + { + unsigned int src_level, box_count, k; + const struct wined3d_box *boxes; + struct wined3d_box b; + + for (i = 0; i < layer_count; ++i) + { + boxes = regions[i].boxes; + box_count = regions[i].box_count; + if (regions[i].box_count >= WINED3D_MAX_DIRTY_REGION_COUNT) + { + boxes = &b; + box_count = 1; + wined3d_texture_get_level_box(dst_texture, i, &b); + } + + for (j = 0; j < level_count; ++j) + { + src_level = j + src_skip_levels; + + /* TODO: We could pass an array of boxes here to avoid + * multiple context acquisitions for the same resource. */ + for (k = 0; k < box_count; ++k) + { + box = boxes[k]; + if (src_level) + { + box.left >>= src_level; + box.top >>= src_level; + box.right = min((box.right + (1u << src_level) - 1) >> src_level, + wined3d_texture_get_level_width(src_texture, src_level)); + box.bottom = min((box.bottom + (1u << src_level) - 1) >> src_level, + wined3d_texture_get_level_height(src_texture, src_level)); + box.front >>= src_level; + box.back = min((box.back + (1u << src_level) - 1) >> src_level, + wined3d_texture_get_level_depth(src_texture, 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); + } + } } }