From: Andrew Boyarshin andrew.boyarshin@gmail.com
--- dlls/d3d8/swapchain.c | 2 +- dlls/d3d9/device.c | 4 +- dlls/d3d9/swapchain.c | 2 +- dlls/ddraw/surface.c | 2 +- dlls/dxgi/swapchain.c | 15 +- dlls/dxgi/tests/dxgi.c | 210 ++++++++--------- dlls/wined3d/surface.c | 2 +- dlls/wined3d/swapchain.c | 476 +++++++++++++++++++++++++++++++++++++- dlls/wined3d/wined3d.spec | 3 +- include/wine/wined3d.h | 12 +- 10 files changed, 612 insertions(+), 116 deletions(-)
diff --git a/dlls/d3d8/swapchain.c b/dlls/d3d8/swapchain.c index 433da09d04b..8f34ea4ccdb 100644 --- a/dlls/d3d8/swapchain.c +++ b/dlls/d3d8/swapchain.c @@ -97,7 +97,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d8_swapchain_Present(IDirect3DSwapChai if (dirty_region) FIXME("Ignoring dirty_region %p.\n", dirty_region);
- return wined3d_swapchain_present(swapchain->wined3d_swapchain, + return wined3d_swapchain_present_legacy(swapchain->wined3d_swapchain, src_rect, dst_rect, dst_window_override, swapchain->swap_interval, 0); }
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 5f59d10079d..5235a6c663e 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -1343,7 +1343,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Present(IDirect3DDevice9Ex * for (i = 0; i < device->implicit_swapchain_count; ++i) { swapchain = wined3d_swapchain_get_parent(device->implicit_swapchains[i]); - if (FAILED(hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, + if (FAILED(hr = wined3d_swapchain_present_legacy(swapchain->wined3d_swapchain, src_rect, dst_rect, dst_window_override, swapchain->swap_interval, 0))) { wined3d_mutex_unlock(); @@ -4266,7 +4266,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_PresentEx(IDirect3DDevice9Ex for (i = 0; i < device->implicit_swapchain_count; ++i) { swapchain = wined3d_swapchain_get_parent(device->implicit_swapchains[i]); - if (FAILED(hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, + if (FAILED(hr = wined3d_swapchain_present_legacy(swapchain->wined3d_swapchain, src_rect, dst_rect, dst_window_override, swapchain->swap_interval, flags))) { wined3d_mutex_unlock(); diff --git a/dlls/d3d9/swapchain.c b/dlls/d3d9/swapchain.c index e87b8627ba3..97bd1c244ca 100644 --- a/dlls/d3d9/swapchain.c +++ b/dlls/d3d9/swapchain.c @@ -150,7 +150,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_swapchain_Present(IDirect3DSwapChai if (dirty_region) FIXME("Ignoring dirty_region %p.\n", dirty_region);
- return wined3d_swapchain_present(swapchain->wined3d_swapchain, + return wined3d_swapchain_present_legacy(swapchain->wined3d_swapchain, src_rect, dst_rect, dst_window_override, swapchain->swap_interval, flags); }
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index 545c76738cd..8d68c579e3a 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -139,7 +139,7 @@ HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, ddraw_surface_get_any_texture(surface, DDRAW_SURFACE_READ), surface->sub_resource_idx, rect, 0, NULL, WINED3D_TEXF_POINT)) && swap_interval) { - hr = wined3d_swapchain_present(ddraw->wined3d_swapchain, rect, rect, NULL, swap_interval, 0); + hr = wined3d_swapchain_present_legacy(ddraw->wined3d_swapchain, rect, rect, NULL, swap_interval, 0); ddraw->flags |= DDRAW_SWAPPED; } return hr; diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index fd790cc7fe2..347567d3268 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -317,6 +317,7 @@ static HRESULT d3d11_swapchain_present(struct d3d11_swapchain *swapchain, unsigned int sync_interval, unsigned int flags, const DXGI_PRESENT_PARAMETERS *dxgi_parameters) { HRESULT hr; + struct wined3d_present_parameters wined3d_parameters;
if (sync_interval > 4) { @@ -335,9 +336,19 @@ static HRESULT d3d11_swapchain_present(struct d3d11_swapchain *swapchain, return S_OK; }
+ wined3d_parameters.swapchain = swapchain->wined3d_swapchain; + wined3d_parameters.swap_interval = sync_interval; + wined3d_parameters.flags = 0; + if (dxgi_parameters && dxgi_parameters->DirtyRectsCount && dxgi_parameters->pDirtyRects) { - FIXME("Ignored %u present dirty rectangles at %p ([0] = %s).\n", dxgi_parameters->DirtyRectsCount, dxgi_parameters->pDirtyRects, wine_dbgstr_rect(&dxgi_parameters->pDirtyRects[0])); + wined3d_parameters.dirty_rectangle_count = dxgi_parameters->DirtyRectsCount; + wined3d_parameters.dirty_rectangles = dxgi_parameters->pDirtyRects; + } + else + { + wined3d_parameters.dirty_rectangle_count = 0; + wined3d_parameters.dirty_rectangles = NULL; }
if (dxgi_parameters && dxgi_has_scroll_present_parameters(dxgi_parameters)) @@ -356,7 +367,7 @@ static HRESULT d3d11_swapchain_present(struct d3d11_swapchain *swapchain, FIXME("Ignored present %s scroll of %s rectangle.\n", wine_dbgstr_point(dxgi_parameters->pScrollOffset), wine_dbgstr_rect(dxgi_parameters->pScrollRect)); }
- if (SUCCEEDED(hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, NULL, NULL, NULL, sync_interval, 0))) + if (SUCCEEDED(hr = wined3d_swapchain_present(&wined3d_parameters))) InterlockedIncrement(&swapchain->present_count); return hr; } diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 812695c2f99..ed968aa46a6 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -8965,7 +8965,7 @@ static void test_partial_present_grid_impl(struct test_partial_present_grid_para const DWORD color_dword = PALETTE_RGBA_DWORD[palette_index];
for (UINT k = 0; k < buffer_count; ++k) - flaky_wine check_texture(backbuffers[k], backbuffer_info[k]->background, buffer_count, backbuffer_info[k]->rectangles); + check_texture(backbuffers[k], backbuffer_info[k]->background, buffer_count, backbuffer_info[k]->rectangles);
ID3D11DeviceContext_ClearRenderTargetView(context, backbuffer_0_rtv, color_float);
@@ -8986,7 +8986,7 @@ static void test_partial_present_grid_impl(struct test_partial_present_grid_para backbuffer_info[k] = backbuffer_info[k + 1];
for (UINT k = 0; k < buffer_count; ++k) - flaky_wine check_texture(backbuffers[k], backbuffer_info[k]->background, buffer_count, backbuffer_info[k]->rectangles); + check_texture(backbuffers[k], backbuffer_info[k]->background, buffer_count, backbuffer_info[k]->rectangles); } }
@@ -9105,60 +9105,60 @@ static void test_partial_present_scroll_impl(struct test_partial_present_common_ check_full(backbuffer_0, BLACK); check_full(backbuffer_1, RED);
- todo_wine check_color(backbuffer_2, 5, 5, RED); - todo_wine check_color(backbuffer_2, 20, 20, RED); - todo_wine check_color(backbuffer_2, 49, 29, RED); - todo_wine check_color(backbuffer_2, 49, 39, RED); - flaky_wine check_colors(backbuffer_2, 49, 49, RED, RED, RED, GREEN); /* top-left corner */ - flaky_wine check_colors(backbuffer_2, 49, 79, RED, GREEN, RED, GREEN); /* left side */ - flaky_wine check_colors(backbuffer_2, 49, 99, RED, GREEN, RED, RED); /* bottom-left corner */ - todo_wine check_color(backbuffer_2, 99, 29, RED); - todo_wine check_color(backbuffer_2, 99, 39, RED); - flaky_wine check_colors(backbuffer_2, 99, 49, RED, RED, GREEN, RED); /* top-right corner */ - flaky_wine check_colors(backbuffer_2, 99, 79, GREEN, RED, GREEN, RED); /* right side */ - flaky_wine check_colors(backbuffer_2, 99, 99, GREEN, RED, RED, RED); /* bottom-right corner */ - todo_wine check_color(backbuffer_2, 199, 59, RED); - todo_wine check_color(backbuffer_2, 399, 59, RED); - flaky_wine check_colors(backbuffer_2, 199, 79, RED, RED, RED, GREEN); /* top-left corner */ - flaky_wine check_colors(backbuffer_2, 399, 79, RED, RED, GREEN, RED); /* top-right corner */ - flaky_wine check_colors(backbuffer_2, 199, 279, RED, GREEN, RED, GREEN); /* left side */ - flaky_wine check_colors(backbuffer_2, 399, 279, GREEN, RED, GREEN, RED); /* right side */ - flaky_wine check_colors(backbuffer_2, 199, 299, RED, GREEN, RED, RED); /* bottom-left corner */ - flaky_wine check_colors(backbuffer_2, 399, 299, GREEN, RED, RED, RED); /* bottom-right corner */ - todo_wine check_color(backbuffer_2, 9, 399, RED); - todo_wine check_color(backbuffer_2, 9, 419, RED); - todo_wine check_color(backbuffer_2, 599, 399, RED); - todo_wine check_color(backbuffer_2, 599, 419, RED); + check_color(backbuffer_2, 5, 5, RED); + check_color(backbuffer_2, 20, 20, RED); + check_color(backbuffer_2, 49, 29, RED); + check_color(backbuffer_2, 49, 39, RED); + check_colors(backbuffer_2, 49, 49, RED, RED, RED, GREEN); /* top-left corner */ + check_colors(backbuffer_2, 49, 79, RED, GREEN, RED, GREEN); /* left side */ + check_colors(backbuffer_2, 49, 99, RED, GREEN, RED, RED); /* bottom-left corner */ + check_color(backbuffer_2, 99, 29, RED); + check_color(backbuffer_2, 99, 39, RED); + check_colors(backbuffer_2, 99, 49, RED, RED, GREEN, RED); /* top-right corner */ + check_colors(backbuffer_2, 99, 79, GREEN, RED, GREEN, RED); /* right side */ + check_colors(backbuffer_2, 99, 99, GREEN, RED, RED, RED); /* bottom-right corner */ + check_color(backbuffer_2, 199, 59, RED); + check_color(backbuffer_2, 399, 59, RED); + check_colors(backbuffer_2, 199, 79, RED, RED, RED, GREEN); /* top-left corner */ + check_colors(backbuffer_2, 399, 79, RED, RED, GREEN, RED); /* top-right corner */ + check_colors(backbuffer_2, 199, 279, RED, GREEN, RED, GREEN); /* left side */ + check_colors(backbuffer_2, 399, 279, GREEN, RED, GREEN, RED); /* right side */ + check_colors(backbuffer_2, 199, 299, RED, GREEN, RED, RED); /* bottom-left corner */ + check_colors(backbuffer_2, 399, 299, GREEN, RED, RED, RED); /* bottom-right corner */ + check_color(backbuffer_2, 9, 399, RED); + check_color(backbuffer_2, 9, 419, RED); + check_color(backbuffer_2, 599, 399, RED); + check_color(backbuffer_2, 599, 419, RED);
ID3D11DeviceContext_ClearRenderTargetView(context, backbuffer_0_rtv, blue);
check_full(backbuffer_0, BLUE); check_full(backbuffer_1, RED);
- todo_wine check_color(backbuffer_2, 5, 5, RED); - todo_wine check_color(backbuffer_2, 20, 20, RED); - todo_wine check_color(backbuffer_2, 49, 29, RED); - todo_wine check_color(backbuffer_2, 49, 39, RED); - flaky_wine check_colors(backbuffer_2, 49, 49, RED, RED, RED, GREEN); /* top-left corner */ - flaky_wine check_colors(backbuffer_2, 49, 79, RED, GREEN, RED, GREEN); /* left side */ - flaky_wine check_colors(backbuffer_2, 49, 99, RED, GREEN, RED, RED); /* bottom-left corner */ - todo_wine check_color(backbuffer_2, 99, 29, RED); - todo_wine check_color(backbuffer_2, 99, 39, RED); - flaky_wine check_colors(backbuffer_2, 99, 49, RED, RED, GREEN, RED); /* top-right corner */ - flaky_wine check_colors(backbuffer_2, 99, 79, GREEN, RED, GREEN, RED); /* right side */ - flaky_wine check_colors(backbuffer_2, 99, 99, GREEN, RED, RED, RED); /* bottom-right corner */ - todo_wine check_color(backbuffer_2, 199, 59, RED); - todo_wine check_color(backbuffer_2, 399, 59, RED); - flaky_wine check_colors(backbuffer_2, 199, 79, RED, RED, RED, GREEN); /* top-left corner */ - flaky_wine check_colors(backbuffer_2, 399, 79, RED, RED, GREEN, RED); /* top-right corner */ - flaky_wine check_colors(backbuffer_2, 199, 279, RED, GREEN, RED, GREEN); /* left side */ - flaky_wine check_colors(backbuffer_2, 399, 279, GREEN, RED, GREEN, RED); /* right side */ - flaky_wine check_colors(backbuffer_2, 199, 299, RED, GREEN, RED, RED); /* bottom-left corner */ - flaky_wine check_colors(backbuffer_2, 399, 299, GREEN, RED, RED, RED); /* bottom-right corner */ - todo_wine check_color(backbuffer_2, 9, 399, RED); - todo_wine check_color(backbuffer_2, 9, 419, RED); - todo_wine check_color(backbuffer_2, 599, 399, RED); - todo_wine check_color(backbuffer_2, 599, 419, RED); + check_color(backbuffer_2, 5, 5, RED); + check_color(backbuffer_2, 20, 20, RED); + check_color(backbuffer_2, 49, 29, RED); + check_color(backbuffer_2, 49, 39, RED); + check_colors(backbuffer_2, 49, 49, RED, RED, RED, GREEN); /* top-left corner */ + check_colors(backbuffer_2, 49, 79, RED, GREEN, RED, GREEN); /* left side */ + check_colors(backbuffer_2, 49, 99, RED, GREEN, RED, RED); /* bottom-left corner */ + check_color(backbuffer_2, 99, 29, RED); + check_color(backbuffer_2, 99, 39, RED); + check_colors(backbuffer_2, 99, 49, RED, RED, GREEN, RED); /* top-right corner */ + check_colors(backbuffer_2, 99, 79, GREEN, RED, GREEN, RED); /* right side */ + check_colors(backbuffer_2, 99, 99, GREEN, RED, RED, RED); /* bottom-right corner */ + check_color(backbuffer_2, 199, 59, RED); + check_color(backbuffer_2, 399, 59, RED); + check_colors(backbuffer_2, 199, 79, RED, RED, RED, GREEN); /* top-left corner */ + check_colors(backbuffer_2, 399, 79, RED, RED, GREEN, RED); /* top-right corner */ + check_colors(backbuffer_2, 199, 279, RED, GREEN, RED, GREEN); /* left side */ + check_colors(backbuffer_2, 399, 279, GREEN, RED, GREEN, RED); /* right side */ + check_colors(backbuffer_2, 199, 299, RED, GREEN, RED, RED); /* bottom-left corner */ + check_colors(backbuffer_2, 399, 299, GREEN, RED, RED, RED); /* bottom-right corner */ + check_color(backbuffer_2, 9, 399, RED); + check_color(backbuffer_2, 9, 419, RED); + check_color(backbuffer_2, 599, 399, RED); + check_color(backbuffer_2, 599, 419, RED);
present_params.DirtyRectsCount = ARRAYSIZE(dirty_rects_blue); present_params.pDirtyRects = dirty_rects_blue; @@ -9173,51 +9173,51 @@ static void test_partial_present_scroll_impl(struct test_partial_present_common_
check_full(backbuffer_0, RED);
- todo_wine check_color(backbuffer_1, 5, 5, RED); - todo_wine check_color(backbuffer_1, 20, 20, RED); - todo_wine check_color(backbuffer_1, 49, 29, RED); - todo_wine check_color(backbuffer_1, 49, 39, RED); - flaky_wine check_colors(backbuffer_1, 49, 49, RED, RED, RED, GREEN); /* top-left corner */ - flaky_wine check_colors(backbuffer_1, 49, 79, RED, GREEN, RED, GREEN); /* left side */ - flaky_wine check_colors(backbuffer_1, 49, 99, RED, GREEN, RED, RED); /* bottom-left corner */ - todo_wine check_color(backbuffer_1, 99, 29, RED); - todo_wine check_color(backbuffer_1, 99, 39, RED); - flaky_wine check_colors(backbuffer_1, 99, 49, RED, RED, GREEN, RED); /* top-right corner */ - flaky_wine check_colors(backbuffer_1, 99, 79, GREEN, RED, GREEN, RED); /* right side */ - flaky_wine check_colors(backbuffer_1, 99, 99, GREEN, RED, RED, RED); /* bottom-right corner */ - todo_wine check_color(backbuffer_1, 199, 59, RED); - todo_wine check_color(backbuffer_1, 399, 59, RED); - flaky_wine check_colors(backbuffer_1, 199, 79, RED, RED, RED, GREEN); /* top-left corner */ - flaky_wine check_colors(backbuffer_1, 399, 79, RED, RED, GREEN, RED); /* top-right corner */ - flaky_wine check_colors(backbuffer_1, 199, 279, RED, GREEN, RED, GREEN); /* left side */ - flaky_wine check_colors(backbuffer_1, 399, 279, GREEN, RED, GREEN, RED); /* right side */ - flaky_wine check_colors(backbuffer_1, 199, 299, RED, GREEN, RED, RED); /* bottom-left corner */ - flaky_wine check_colors(backbuffer_1, 399, 299, GREEN, RED, RED, RED); /* bottom-right corner */ - todo_wine check_color(backbuffer_1, 9, 399, RED); - todo_wine check_color(backbuffer_1, 9, 419, RED); - todo_wine check_color(backbuffer_1, 599, 399, RED); - todo_wine check_color(backbuffer_1, 599, 419, RED); - - todo_wine check_color(backbuffer_2, 5, 5, RED); - todo_wine check_color(backbuffer_2, 20, 20, RED); + check_color(backbuffer_1, 5, 5, RED); + check_color(backbuffer_1, 20, 20, RED); + check_color(backbuffer_1, 49, 29, RED); + check_color(backbuffer_1, 49, 39, RED); + check_colors(backbuffer_1, 49, 49, RED, RED, RED, GREEN); /* top-left corner */ + check_colors(backbuffer_1, 49, 79, RED, GREEN, RED, GREEN); /* left side */ + check_colors(backbuffer_1, 49, 99, RED, GREEN, RED, RED); /* bottom-left corner */ + check_color(backbuffer_1, 99, 29, RED); + check_color(backbuffer_1, 99, 39, RED); + check_colors(backbuffer_1, 99, 49, RED, RED, GREEN, RED); /* top-right corner */ + check_colors(backbuffer_1, 99, 79, GREEN, RED, GREEN, RED); /* right side */ + check_colors(backbuffer_1, 99, 99, GREEN, RED, RED, RED); /* bottom-right corner */ + check_color(backbuffer_1, 199, 59, RED); + check_color(backbuffer_1, 399, 59, RED); + check_colors(backbuffer_1, 199, 79, RED, RED, RED, GREEN); /* top-left corner */ + check_colors(backbuffer_1, 399, 79, RED, RED, GREEN, RED); /* top-right corner */ + check_colors(backbuffer_1, 199, 279, RED, GREEN, RED, GREEN); /* left side */ + check_colors(backbuffer_1, 399, 279, GREEN, RED, GREEN, RED); /* right side */ + check_colors(backbuffer_1, 199, 299, RED, GREEN, RED, RED); /* bottom-left corner */ + check_colors(backbuffer_1, 399, 299, GREEN, RED, RED, RED); /* bottom-right corner */ + check_color(backbuffer_1, 9, 399, RED); + check_color(backbuffer_1, 9, 419, RED); + check_color(backbuffer_1, 599, 399, RED); + check_color(backbuffer_1, 599, 419, RED); + + check_color(backbuffer_2, 5, 5, RED); + check_color(backbuffer_2, 20, 20, RED); flaky_wine check_colors(backbuffer_2, 49, 29, RED, RED, RED, GREEN); /* top-left corner */ flaky_wine check_colors(backbuffer_2, 49, 39, RED, GREEN, RED, BLUE); /* left side, green-blue edge */ flaky_wine check_colors(backbuffer_2, 49, 49, RED, BLUE, RED, BLUE); /* left side */ flaky_wine check_colors(backbuffer_2, 49, 79, RED, BLUE, RED, RED); /* bottom-left corner */ - todo_wine check_color(backbuffer_2, 49, 99, RED); + flaky_wine check_color(backbuffer_2, 49, 99, RED); flaky_wine check_colors(backbuffer_2, 99, 29, RED, RED, GREEN, RED); /* top-right corner */ flaky_wine check_colors(backbuffer_2, 99, 39, GREEN, RED, BLUE, RED); /* right side, green-blue edge */ flaky_wine check_colors(backbuffer_2, 99, 49, BLUE, RED, BLUE, RED); /* right side */ flaky_wine check_colors(backbuffer_2, 99, 79, BLUE, RED, RED, RED); /* bottom-right corner */ - todo_wine check_color(backbuffer_2, 99, 99, RED); + flaky_wine check_color(backbuffer_2, 99, 99, RED); flaky_wine check_colors(backbuffer_2, 199, 59, RED, RED, RED, GREEN); /* top-left corner */ flaky_wine check_colors(backbuffer_2, 399, 59, RED, RED, GREEN, RED); /* top-right corner */ flaky_wine check_colors(backbuffer_2, 199, 79, RED, GREEN, RED, GREEN); /* left side */ flaky_wine check_colors(backbuffer_2, 399, 79, GREEN, RED, GREEN, RED); /* right side */ flaky_wine check_colors(backbuffer_2, 199, 279, RED, GREEN, RED, RED); /* bottom-left corner */ flaky_wine check_colors(backbuffer_2, 399, 279, GREEN, RED, RED, RED); /* bottom-right corner */ - todo_wine check_color(backbuffer_2, 199, 299, RED); - todo_wine check_color(backbuffer_2, 399, 299, RED); + flaky_wine check_color(backbuffer_2, 199, 299, RED); + flaky_wine check_color(backbuffer_2, 399, 299, RED); flaky_wine check_colors(backbuffer_2, 9, 399, RED, RED, RED, BLUE); /* top-left corner */ flaky_wine check_colors(backbuffer_2, 9, 419, RED, BLUE, RED, RED); /* bottom-left corner */ flaky_wine check_colors(backbuffer_2, 599, 399, RED, RED, BLUE, RED); /* top-right corner */ @@ -9232,30 +9232,30 @@ static void test_partial_present_scroll_impl(struct test_partial_present_common_ check_full(backbuffer_0, BLUE); check_full(backbuffer_1, RED);
- todo_wine check_color(backbuffer_2, 5, 5, RED); - todo_wine check_color(backbuffer_2, 20, 20, RED); - todo_wine check_color(backbuffer_2, 49, 29, RED); - todo_wine check_color(backbuffer_2, 49, 39, RED); - flaky_wine check_colors(backbuffer_2, 49, 49, RED, RED, RED, GREEN); /* top-left corner */ - flaky_wine check_colors(backbuffer_2, 49, 79, RED, GREEN, RED, GREEN); /* left side */ - flaky_wine check_colors(backbuffer_2, 49, 99, RED, GREEN, RED, RED); /* bottom-left corner */ - todo_wine check_color(backbuffer_2, 99, 29, RED); - todo_wine check_color(backbuffer_2, 99, 39, RED); - flaky_wine check_colors(backbuffer_2, 99, 49, RED, RED, GREEN, RED); /* top-right corner */ - flaky_wine check_colors(backbuffer_2, 99, 79, GREEN, RED, GREEN, RED); /* right side */ - flaky_wine check_colors(backbuffer_2, 99, 99, GREEN, RED, RED, RED); /* bottom-right corner */ - todo_wine check_color(backbuffer_2, 199, 59, RED); - todo_wine check_color(backbuffer_2, 399, 59, RED); - flaky_wine check_colors(backbuffer_2, 199, 79, RED, RED, RED, GREEN); /* top-left corner */ - flaky_wine check_colors(backbuffer_2, 399, 79, RED, RED, GREEN, RED); /* top-right corner */ - flaky_wine check_colors(backbuffer_2, 199, 279, RED, GREEN, RED, GREEN); /* left side */ - flaky_wine check_colors(backbuffer_2, 399, 279, GREEN, RED, GREEN, RED); /* right side */ - flaky_wine check_colors(backbuffer_2, 199, 299, RED, GREEN, RED, RED); /* bottom-left corner */ - flaky_wine check_colors(backbuffer_2, 399, 299, GREEN, RED, RED, RED); /* bottom-right corner */ - todo_wine check_color(backbuffer_2, 9, 399, RED); - todo_wine check_color(backbuffer_2, 9, 419, RED); - todo_wine check_color(backbuffer_2, 599, 399, RED); - todo_wine check_color(backbuffer_2, 599, 419, RED); + check_color(backbuffer_2, 5, 5, RED); + check_color(backbuffer_2, 20, 20, RED); + check_color(backbuffer_2, 49, 29, RED); + check_color(backbuffer_2, 49, 39, RED); + check_colors(backbuffer_2, 49, 49, RED, RED, RED, GREEN); /* top-left corner */ + check_colors(backbuffer_2, 49, 79, RED, GREEN, RED, GREEN); /* left side */ + check_colors(backbuffer_2, 49, 99, RED, GREEN, RED, RED); /* bottom-left corner */ + check_color(backbuffer_2, 99, 29, RED); + check_color(backbuffer_2, 99, 39, RED); + check_colors(backbuffer_2, 99, 49, RED, RED, GREEN, RED); /* top-right corner */ + check_colors(backbuffer_2, 99, 79, GREEN, RED, GREEN, RED); /* right side */ + check_colors(backbuffer_2, 99, 99, GREEN, RED, RED, RED); /* bottom-right corner */ + check_color(backbuffer_2, 199, 59, RED); + check_color(backbuffer_2, 399, 59, RED); + check_colors(backbuffer_2, 199, 79, RED, RED, RED, GREEN); /* top-left corner */ + check_colors(backbuffer_2, 399, 79, RED, RED, GREEN, RED); /* top-right corner */ + check_colors(backbuffer_2, 199, 279, RED, GREEN, RED, GREEN); /* left side */ + check_colors(backbuffer_2, 399, 279, GREEN, RED, GREEN, RED); /* right side */ + check_colors(backbuffer_2, 199, 299, RED, GREEN, RED, RED); /* bottom-left corner */ + check_colors(backbuffer_2, 399, 299, GREEN, RED, RED, RED); /* bottom-right corner */ + check_color(backbuffer_2, 9, 399, RED); + check_color(backbuffer_2, 9, 419, RED); + check_color(backbuffer_2, 599, 399, RED); + check_color(backbuffer_2, 599, 419, RED); }
ID3D11RenderTargetView_Release(backbuffer_0_rtv); diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 3389f5fb866..a37377ba935 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1601,7 +1601,7 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ /* Set the swap effect to COPY, we don't want the backbuffer to become * undefined. */ dst_swapchain->state.desc.swap_effect = WINED3D_SWAP_EFFECT_COPY; - wined3d_swapchain_present(dst_swapchain, NULL, NULL, + wined3d_swapchain_present_legacy(dst_swapchain, NULL, NULL, dst_swapchain->win_handle, dst_swapchain->swap_interval, 0); dst_swapchain->state.desc.swap_effect = swap_effect;
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index a59936fd468..874f002a87d 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -27,6 +27,205 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
+static const char *wine_dbgstr_rgn( HRGN hrgn ) +{ + DWORD i, size; + RGNDATA *data = NULL; + RECT *rect; + char buffer[200]; + int buffer_position = 0; + + if (!hrgn) return "(null)"; + + if (!(size = GetRegionData(hrgn, 0, NULL))) return "(ERROR)"; + if (!(data = malloc(size))) return "(NOMEM)"; + GetRegionData(hrgn, size, data); + + if (buffer_position < ARRAYSIZE(buffer)) + buffer_position += snprintf(buffer + buffer_position, ARRAYSIZE(buffer) - buffer_position, "{"); + + for (i = 0, rect = (RECT *) data->Buffer; i < data->rdh.nCount; ++i, ++rect) + { + if (i != 0 && buffer_position < ARRAYSIZE(buffer)) + buffer_position += snprintf(buffer + buffer_position, ARRAYSIZE(buffer) - buffer_position, ", "); + + if (buffer_position < ARRAYSIZE(buffer)) + buffer_position += snprintf(buffer + buffer_position, ARRAYSIZE(buffer) - buffer_position, "%s", wine_dbgstr_rect(rect)); + } + + free(data); + + if (buffer_position < ARRAYSIZE(buffer)) + buffer_position += snprintf(buffer + buffer_position, ARRAYSIZE(buffer) - buffer_position, "}"); + + buffer[ARRAYSIZE(buffer) - 1] = 0; + return __wine_dbg_strdup(buffer); +} + +static void region_set(HRGN *region, const RECT *rect) +{ + HRGN hrgn = *region; + + TRACE("region %p %s, rect %s.\n", region, wine_dbgstr_rgn(hrgn), wine_dbgstr_rect(rect)); + + if (hrgn) + { + if (!SetRectRgn(hrgn, rect->left, rect->top, rect->right, rect->bottom)) + ERR("Failed to update region %p with %s.\n", hrgn, wine_dbgstr_rect(rect)); + } + else + { + *region = hrgn = CreateRectRgnIndirect(rect); + if (!hrgn) + ERR("Failed to create region from %s.\n", wine_dbgstr_rect(rect)); + } +} + +static INT region_combine_region(HRGN *region, HRGN other, INT mode) +{ + HRGN hrgn = *region; + INT result; + + TRACE("region %p %p %s, other %p %s, mode %d.\n", + region, hrgn, wine_dbgstr_rgn(hrgn), other, wine_dbgstr_rgn(other), mode); + + if (hrgn && other) + { + /* CombineRgn only works well with non-NULL destination and sources */ + result = CombineRgn(hrgn, hrgn, other, mode); + } + else if (hrgn) + { + /* lhs != NULL, rhs == NULL */ + switch (mode) + { + case RGN_AND: + if (!SetRectRgn(hrgn, 0, 0, 0, 0)) + { + ERR("Failed to clear region %p.\n", hrgn); + return ERROR; + } + return NULLREGION; + case RGN_OR: + case RGN_XOR: + case RGN_DIFF: + case RGN_COPY: + result = CombineRgn(hrgn, hrgn, NULL, RGN_COPY); + break; + default: + ERR("Invalid CombineRgn mode %d.\n", mode); + return ERROR; + } + } + else if (other) + { + /* lhs == NULL, rhs != NULL */ + switch (mode) + { + case RGN_AND: + case RGN_DIFF: + case RGN_COPY: + return NULLREGION; + case RGN_OR: + case RGN_XOR: + *region = hrgn = CreateRectRgn(0, 0, 0, 0); + result = CombineRgn(hrgn, other, NULL, RGN_COPY); + break; + default: + ERR("Invalid CombineRgn mode %d.\n", mode); + return ERROR; + } + } + else + { + /* lhs == NULL, rhs == NULL */ + return NULLREGION; + } + if (result == ERROR) + { + ERR("CombineRgn(%p, %p, %d) failed.\n", *region, other, mode); + } + return result; +} + +static INT region_combine_rect(HRGN *region, const RECT *other, INT mode) +{ + HRGN hrgn = *region; + INT result; + + TRACE("region %p %p %s, other %s, mode %d.\n", + region, hrgn, wine_dbgstr_rgn(hrgn), wine_dbgstr_rect(other), mode); + + if (hrgn && !IsRectEmpty(other)) + { + /* lhs != NULL, rhs != NULL */ + HRGN other_region = CreateRectRgnIndirect(other); + if (!other_region) + { + ERR("Failed to create region from %s.\n", wine_dbgstr_rect(other)); + return ERROR; + } + + result = CombineRgn(hrgn, hrgn, other_region, mode); + } + else if (hrgn) + { + /* lhs != NULL, rhs == NULL */ + switch (mode) + { + case RGN_AND: + if (!SetRectRgn(hrgn, 0, 0, 0, 0)) + { + ERR("Failed to clear region %p.\n", hrgn); + return ERROR; + } + return NULLREGION; + case RGN_OR: + case RGN_XOR: + case RGN_DIFF: + case RGN_COPY: + result = CombineRgn(hrgn, hrgn, NULL, RGN_COPY); + break; + default: + ERR("Invalid CombineRgn mode %d.\n", mode); + return ERROR; + } + } + else if (!IsRectEmpty(other)) + { + /* lhs == NULL, rhs != NULL */ + switch (mode) + { + case RGN_AND: + case RGN_DIFF: + case RGN_COPY: + return NULLREGION; + case RGN_OR: + case RGN_XOR: + *region = hrgn = CreateRectRgnIndirect(other); + if (!hrgn) + { + ERR("Failed to create region from %s.\n", wine_dbgstr_rect(other)); + return ERROR; + } + return SIMPLEREGION; + default: + ERR("Invalid CombineRgn mode %d.\n", mode); + return ERROR; + } + } + else + { + /* lhs == NULL, rhs == NULL */ + return NULLREGION; + } + if (result == ERROR) + { + ERR("CombineRgn(%p, %p, %d) failed.\n", *region, other, mode); + } + return result; +} + void wined3d_swapchain_cleanup(struct wined3d_swapchain *swapchain) { HRESULT hr; @@ -191,7 +390,7 @@ void CDECL wined3d_swapchain_set_window(struct wined3d_swapchain *swapchain, HWN swapchain->win_handle = window; }
-HRESULT CDECL wined3d_swapchain_present(struct wined3d_swapchain *swapchain, +HRESULT CDECL wined3d_swapchain_present_legacy(struct wined3d_swapchain *swapchain, const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, unsigned int swap_interval, uint32_t flags) { @@ -226,6 +425,8 @@ HRESULT CDECL wined3d_swapchain_present(struct wined3d_swapchain *swapchain, dst_rect = &d; }
+ region_set(&swapchain->back_buffers[0].dirty_region, src_rect); + wined3d_cs_emit_present(swapchain->device->cs, swapchain, src_rect, dst_rect, dst_window_override, swap_interval, flags);
@@ -234,6 +435,279 @@ HRESULT CDECL wined3d_swapchain_present(struct wined3d_swapchain *swapchain, return WINED3D_OK; }
+static HRESULT present_region_blit(struct wined3d_swapchain *swapchain, + struct wined3d_texture *src_texture, struct wined3d_texture *dst_texture, HRGN region) +{ + DWORD region_data_size_expected, region_data_size_actual; + RGNDATA *region_data = NULL; + struct wined3d_device_context *context; + HRESULT hr; + RECT bounds; + + TRACE("swapchain %p, src_texture %p, dst_texture %p, region %p %s.\n", + swapchain, src_texture, dst_texture, region, wine_dbgstr_rgn(region)); + + region_data_size_expected = GetRegionData(region, 0, NULL); + region_data = malloc(region_data_size_expected); + if (!region_data) + { + ERR("Failed to allocate %lu bytes.\n", region_data_size_expected); + hr = E_OUTOFMEMORY; + goto state_cleanup; + } + + region_data_size_actual = GetRegionData(region, region_data_size_expected, region_data); + if (!region_data_size_actual) + { + DWORD error = GetLastError(); + ERR("Failed to acquire region data, error %#lx.\n", error); + hr = HRESULT_FROM_WIN32(error); + goto state_cleanup; + } + + hr = S_OK; + context = wined3d_device_get_immediate_context(swapchain->device); + SetRect(&bounds, 0, 0, dst_texture->resource.width, dst_texture->resource.height); + + for (DWORD i = 0; i < region_data->rdh.nCount; ++i) + { + RECT dst_rect = ((const RECT *) region_data->Buffer)[i]; + RECT clipped_dst_rect; + RECT src_rect; + + if (!IntersectRect(&clipped_dst_rect, &dst_rect, &bounds)) + { + TRACE("Destination rect %s is completely out of bounds after clipping to %s.\n", + wine_dbgstr_rect(&dst_rect), wine_dbgstr_rect(&bounds)); + continue; + } + + if (!EqualRect(&dst_rect, &clipped_dst_rect)) + { + TRACE("Destination rect %s clipped to %s is %s.\n", + wine_dbgstr_rect(&dst_rect), wine_dbgstr_rect(&bounds), wine_dbgstr_rect(&clipped_dst_rect)); + dst_rect = clipped_dst_rect; + } + + src_rect = dst_rect; + + hr = wined3d_device_context_blt(context, dst_texture, 0, &dst_rect, src_texture, 0, &src_rect, WINED3D_BLT_RAW, NULL, WINED3D_TEXF_POINT); + if (FAILED(hr)) + { + ERR("Failed to blit region #%lu: %s -> %s.\n", i, wine_dbgstr_rect(&src_rect), wine_dbgstr_rect(&dst_rect)); + break; + } + } + +state_cleanup: + free(region_data); + return hr; +} + +HRESULT CDECL present_partial_compute_dirty(struct wined3d_present_parameters *parameters) +{ + struct wined3d_swapchain *swapchain = parameters->swapchain; + struct wined3d_swapchain_desc *desc = &swapchain->state.desc; + UINT backbuffer_count = desc->backbuffer_count; + struct wined3d_backbuffer *backbuffer_0 = &swapchain->back_buffers[0]; + struct wined3d_backbuffer *backbuffer_prev = &swapchain->back_buffers[backbuffer_count - 1]; + unsigned int backbuffer_width = desc->backbuffer_width; + unsigned int backbuffer_height = desc->backbuffer_height; + HRGN blt_region = NULL; + RECT backbuffer_rect; + INT region_kind; + + SetRect(&backbuffer_rect, 0, 0, backbuffer_width, backbuffer_height); + + if (parameters->dirty_rectangle_count) + { + if (backbuffer_0->dirty_region) + { + SetRectRgn(backbuffer_0->dirty_region, 0, 0, 0, 0); + } + + for (UINT i = 0; i < parameters->dirty_rectangle_count; ++i) + { + RECT dirty_rect = parameters->dirty_rectangles[i]; + region_combine_rect(&backbuffer_0->dirty_region, &dirty_rect, RGN_OR); + } + } + else + { + region_set(&backbuffer_0->dirty_region, &backbuffer_rect); + } + + for (UINT i = 1; i < backbuffer_count; ++i) + { + struct wined3d_backbuffer *backbuffer = &swapchain->back_buffers[i]; + region_combine_region(&blt_region, backbuffer->dirty_region, RGN_OR); + } + + TRACE("dirty_other = %p %s\n", blt_region, wine_dbgstr_rgn(blt_region)); + TRACE("dirty_0 = %p %s\n", backbuffer_0->dirty_region, wine_dbgstr_rgn(backbuffer_0->dirty_region)); + + region_kind = region_combine_region(&blt_region, backbuffer_0->dirty_region, RGN_DIFF); + TRACE("blt_region = [%d] %p %s\n", region_kind, blt_region, wine_dbgstr_rgn(blt_region)); + + if (region_kind != NULLREGION) + present_region_blit(swapchain, backbuffer_prev->texture, backbuffer_0->texture, blt_region); + + if (blt_region) + DeleteObject(blt_region); + + return S_OK; +} + +void CDECL present_transform_dirty_rect(SIZE *swapchain, SIZE *client, RECT *src_rect, RECT *dst_rect) +{ + DOUBLE scale_x, scale_y; + if (!client->cx || !client->cy || !swapchain->cx || !swapchain->cy) + { + SetRectEmpty(dst_rect); + return; + } + + /* + * TODO: consider supporting scaling other that DXGI_SCALING_STRETCH: + * * DXGI_SCALING_NONE should copy src_rect to dst_rect + * * DXGI_SCALING_ASPECT_RATIO_STRETCH should apply letterboxing, a bit more complex than simple stretch + */ + scale_x = client->cx / swapchain->cx; + scale_y = client->cy / swapchain->cy; + dst_rect->left = floor(scale_x * src_rect->left); + dst_rect->top = floor(scale_y * src_rect->top); + dst_rect->right = ceil(scale_x * src_rect->right); + dst_rect->bottom = ceil(scale_y * src_rect->bottom); +} + +HRESULT CDECL present_partial_as_cs_op(struct wined3d_present_parameters *parameters, RECT *src_rect, RECT *dst_rect) +{ + struct wined3d_swapchain *swapchain = parameters->swapchain; + struct wined3d_swapchain_desc *desc = &swapchain->state.desc; + HRGN dirty_region_0 = swapchain->back_buffers[0].dirty_region; + DWORD region_data_size_expected, region_data_size_actual; + SIZE swapchain_size, client_size; + DWORD final_dirty_rectangle_count; + RECT client_rect; + RGNDATA *region_data = NULL; + HRESULT hr; + + swapchain_size.cx = desc->backbuffer_width; + swapchain_size.cy = desc->backbuffer_height; + GetClientRect(parameters->swapchain->win_handle, &client_rect); + client_size.cx = client_rect.right - client_rect.left; + client_size.cy = client_rect.bottom - client_rect.top; + + region_data_size_expected = GetRegionData(dirty_region_0, 0, NULL); + region_data = malloc(region_data_size_expected); + if (!region_data) + { + ERR("Failed to allocate %lu bytes.\n", region_data_size_expected); + hr = E_OUTOFMEMORY; + goto state_cleanup; + } + + region_data_size_actual = GetRegionData(dirty_region_0, region_data_size_expected, region_data); + if (!region_data_size_actual) + { + DWORD error = GetLastError(); + ERR("Failed to acquire region data, error %#lx.\n", error); + hr = HRESULT_FROM_WIN32(error); + goto state_cleanup; + } + + final_dirty_rectangle_count = region_data->rdh.nCount; + if (final_dirty_rectangle_count == 1) + { + RECT dirty_rect = ((const RECT *) region_data->Buffer)[0]; + + *src_rect = dirty_rect; + present_transform_dirty_rect(&swapchain_size, &client_size, src_rect, dst_rect); + } + else if (final_dirty_rectangle_count > 1) + { + FIXME("Multiple (%lu) dirty rectangles are not properly supported.\n", final_dirty_rectangle_count); + + *src_rect = region_data->rdh.rcBound; + present_transform_dirty_rect(&swapchain_size, &client_size, src_rect, dst_rect); + } + else + { + SetRectEmpty(src_rect); + SetRectEmpty(dst_rect); + } + + hr = S_OK; + +state_cleanup: + free(region_data); + + return hr; +} + +HRESULT CDECL wined3d_swapchain_present(struct wined3d_present_parameters *parameters) +{ + struct wined3d_swapchain *swapchain = parameters->swapchain; + uint32_t flags = parameters->flags; + struct wined3d_backbuffer *back_buffers; + HRESULT hr; + RECT src_rect, dst_rect; + + TRACE("swapchain %p, swap_interval %u, flags %#x, dirty_rectangle_count %u.\n", + swapchain, parameters->swap_interval, flags, parameters->dirty_rectangle_count); + + if (flags) + FIXME("Ignoring flags %#x.\n", flags); + + wined3d_mutex_lock(); + + back_buffers = swapchain->back_buffers; + if (!back_buffers) + { + WARN("Swapchain doesn't have a backbuffer, returning WINED3DERR_INVALIDCALL.\n"); + hr = WINED3DERR_INVALIDCALL; + goto cleanup; + } + + if (parameters->dirty_rectangle_count) + { + /* Partial presentation */ + if (FAILED(hr = present_partial_compute_dirty(parameters))) + { + goto cleanup; + } + + if (FAILED(hr = present_partial_as_cs_op(parameters, &src_rect, &dst_rect))) + { + goto cleanup; + } + } + else + { + /* Full presentation */ + struct wined3d_swapchain_desc *desc = &swapchain->state.desc; + struct wined3d_backbuffer *backbuffer_0 = &back_buffers[0]; + RECT backbuffer_rect; + + SetRect(&backbuffer_rect, 0, 0, desc->backbuffer_width, desc->backbuffer_height); + + region_set(&backbuffer_0->dirty_region, &backbuffer_rect); + + src_rect = backbuffer_rect; + GetClientRect(parameters->swapchain->win_handle, &dst_rect); + } + + wined3d_cs_emit_present(swapchain->device->cs, swapchain, &src_rect, + &dst_rect, NULL, parameters->swap_interval, flags); + + hr = WINED3D_OK; + +cleanup: + wined3d_mutex_unlock(); + + return hr; +} + HRESULT CDECL wined3d_swapchain_get_front_buffer_data(const struct wined3d_swapchain *swapchain, struct wined3d_texture *dst_texture, unsigned int sub_resource_idx) { diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 94e418ca885..ee2fda3fe8c 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -306,7 +306,8 @@ @ cdecl wined3d_swapchain_get_raster_status(ptr ptr) @ cdecl wined3d_swapchain_get_state(ptr) @ cdecl wined3d_swapchain_incref(ptr) -@ cdecl wined3d_swapchain_present(ptr ptr ptr ptr long long) +@ cdecl wined3d_swapchain_present_legacy(ptr ptr ptr ptr long long) +@ cdecl wined3d_swapchain_present(ptr) @ cdecl wined3d_swapchain_resize_buffers(ptr long long long long long long) @ cdecl wined3d_swapchain_set_gamma_ramp(ptr long ptr) @ cdecl wined3d_swapchain_set_palette(ptr ptr) diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index a3d449f14c6..be0de4c36b0 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2318,6 +2318,15 @@ struct wined3d_streaming_buffer unsigned int bind_flags; };
+struct wined3d_present_parameters +{ + struct wined3d_swapchain *swapchain; + unsigned int swap_interval; + uint32_t flags; + uint32_t dirty_rectangle_count; + RECT *dirty_rectangles; +}; + void __stdcall wined3d_mutex_lock(void); void __stdcall wined3d_mutex_unlock(void);
@@ -2901,8 +2910,9 @@ HRESULT __cdecl wined3d_swapchain_get_raster_status(const struct wined3d_swapcha struct wined3d_raster_status *raster_status); struct wined3d_swapchain_state * __cdecl wined3d_swapchain_get_state(struct wined3d_swapchain *swapchain); ULONG __cdecl wined3d_swapchain_incref(struct wined3d_swapchain *swapchain); -HRESULT __cdecl wined3d_swapchain_present(struct wined3d_swapchain *swapchain, const RECT *src_rect, +HRESULT __cdecl wined3d_swapchain_present_legacy(struct wined3d_swapchain *swapchain, const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, unsigned int swap_interval, uint32_t flags); +HRESULT __cdecl wined3d_swapchain_present(struct wined3d_present_parameters *parameters); HRESULT __cdecl wined3d_swapchain_resize_buffers(struct wined3d_swapchain *swapchain, unsigned int buffer_count, unsigned int width, unsigned int height, enum wined3d_format_id format_id, enum wined3d_multisample_type multisample_type, unsigned int multisample_quality);