[PATCH 0/5] MR11249: Implement sprite batches.
From: Santino Mazza <smazza@codeweavers.com> To introduce compare_rect_u. --- dlls/d2d1/tests/d2d1.c | 86 +++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index c01c6eefde4..afda90f1271 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -901,7 +901,7 @@ static BOOL compare_point(const D2D1_POINT_2F *point, float x, float y, unsigned && compare_float(point->y, y, ulps); } -static BOOL compare_rect(const D2D1_RECT_F *rect, float left, float top, float right, float bottom, unsigned int ulps) +static BOOL compare_rect_f(const D2D1_RECT_F *rect, float left, float top, float right, float bottom, unsigned int ulps) { return compare_float(rect->left, left, ulps) && compare_float(rect->top, top, ulps) @@ -3099,7 +3099,7 @@ static void test_image_brush(BOOL d3d11) matrix._11, matrix._12, matrix._21, matrix._22, matrix._31, matrix._32); ID2D1ImageBrush_GetSourceRectangle(brush, &rect); - match = compare_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f, 0); + match = compare_rect_f(&rect, 1.0f, 2.0f, 3.0f, 4.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -4219,7 +4219,7 @@ static void test_path_geometry(BOOL d3d11) set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f); hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 123.0f, 456.0f, 123.0f, 456.0f, 0); + match = compare_rect_f(&rect, 123.0f, 456.0f, 123.0f, 456.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -4228,7 +4228,7 @@ static void test_path_geometry(BOOL d3d11) scale_matrix(&matrix, 2.0f, 0.5f); hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 326.0f, 868.0f, 326.0f, 868.0f, 0); + match = compare_rect_f(&rect, 326.0f, 868.0f, 326.0f, 868.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -4264,7 +4264,7 @@ static void test_path_geometry(BOOL d3d11) set_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f); hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect); ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f, 0); + match = compare_rect_f(&rect, 1.0f, 2.0f, 3.0f, 4.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -4275,7 +4275,7 @@ static void test_path_geometry(BOOL d3d11) set_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f); hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect); ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f, 0); + match = compare_rect_f(&rect, 1.0f, 2.0f, 3.0f, 4.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -4319,7 +4319,7 @@ static void test_path_geometry(BOOL d3d11) set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f); hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 5.0f, 20.0f, 75.0f, 752.0f, 0); + match = compare_rect_f(&rect, 5.0f, 20.0f, 75.0f, 752.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -4329,7 +4329,7 @@ static void test_path_geometry(BOOL d3d11) set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f); hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 90.0f, 650.0f, 230.0f, 1016.0f, 0); + match = compare_rect_f(&rect, 90.0f, 650.0f, 230.0f, 1016.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -4348,7 +4348,7 @@ static void test_path_geometry(BOOL d3d11) set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f); hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 5.0f, 472.0f, 75.0f, 752.0f, 0); + match = compare_rect_f(&rect, 5.0f, 472.0f, 75.0f, 752.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -4358,7 +4358,7 @@ static void test_path_geometry(BOOL d3d11) set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f); hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 90.0f, 876.0f, 230.0f, 1016.0f, 0); + match = compare_rect_f(&rect, 90.0f, 876.0f, 230.0f, 1016.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -4377,7 +4377,7 @@ static void test_path_geometry(BOOL d3d11) set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f); hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, INFINITY, INFINITY, FLT_MAX, FLT_MAX, 0); + match = compare_rect_f(&rect, INFINITY, INFINITY, FLT_MAX, FLT_MAX, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -4387,7 +4387,7 @@ static void test_path_geometry(BOOL d3d11) set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f); hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, INFINITY, INFINITY, FLT_MAX, FLT_MAX, 0); + match = compare_rect_f(&rect, INFINITY, INFINITY, FLT_MAX, FLT_MAX, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -4509,7 +4509,7 @@ static void test_path_geometry(BOOL d3d11) set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f); hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 5.0f, 20.0f, 235.0f, 300.0f, 0); + match = compare_rect_f(&rect, 5.0f, 20.0f, 235.0f, 300.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -4520,7 +4520,7 @@ static void test_path_geometry(BOOL d3d11) set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f); hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, -3.17192993e+02f, 8.71231079e+01f, 4.04055908e+02f, 6.17453125e+02f, 1); + match = compare_rect_f(&rect, -3.17192993e+02f, 8.71231079e+01f, 4.04055908e+02f, 6.17453125e+02f, 1); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -4831,7 +4831,7 @@ static void test_path_geometry(BOOL d3d11) set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f); hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 20.0f, 20.0f, 180.0f, 180.0f, 0); + match = compare_rect_f(&rect, 20.0f, 20.0f, 180.0f, 180.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -4956,7 +4956,7 @@ static void test_rectangle_geometry(BOOL d3d11) hr = ID2D1Factory_CreateRectangleGeometry(ctx.factory, &rect, &geometry); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ID2D1RectangleGeometry_GetRect(geometry, &rect2); - match = compare_rect(&rect2, 0.0f, 0.0f, 0.0f, 0.0f, 0); + match = compare_rect_f(&rect2, 0.0f, 0.0f, 0.0f, 0.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect2.left, rect2.top, rect2.right, rect2.bottom); ID2D1RectangleGeometry_Release(geometry); @@ -4965,7 +4965,7 @@ static void test_rectangle_geometry(BOOL d3d11) hr = ID2D1Factory_CreateRectangleGeometry(ctx.factory, &rect, &geometry); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ID2D1RectangleGeometry_GetRect(geometry, &rect2); - match = compare_rect(&rect2, 50.0f, 0.0f, 40.0f, 100.0f, 0); + match = compare_rect_f(&rect2, 50.0f, 0.0f, 40.0f, 100.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect2.left, rect2.top, rect2.right, rect2.bottom); ID2D1RectangleGeometry_Release(geometry); @@ -4974,7 +4974,7 @@ static void test_rectangle_geometry(BOOL d3d11) hr = ID2D1Factory_CreateRectangleGeometry(ctx.factory, &rect, &geometry); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ID2D1RectangleGeometry_GetRect(geometry, &rect2); - match = compare_rect(&rect2, 0.0f, 100.0f, 40.0f, 50.0f, 0); + match = compare_rect_f(&rect2, 0.0f, 100.0f, 40.0f, 50.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect2.left, rect2.top, rect2.right, rect2.bottom); ID2D1RectangleGeometry_Release(geometry); @@ -4983,7 +4983,7 @@ static void test_rectangle_geometry(BOOL d3d11) hr = ID2D1Factory_CreateRectangleGeometry(ctx.factory, &rect, &geometry); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ID2D1RectangleGeometry_GetRect(geometry, &rect2); - match = compare_rect(&rect2, 50.0f, 100.0f, 40.0f, 50.0f, 0); + match = compare_rect_f(&rect2, 50.0f, 100.0f, 40.0f, 50.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect2.left, rect2.top, rect2.right, rect2.bottom); ID2D1RectangleGeometry_Release(geometry); @@ -5034,7 +5034,7 @@ static void test_rectangle_geometry(BOOL d3d11) /* Test GetBounds() and Simplify(). */ hr = ID2D1RectangleGeometry_GetBounds(geometry, NULL, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 0.0f, 0.0f, 10.0f, 20.0f, 0); + match = compare_rect_f(&rect, 0.0f, 0.0f, 10.0f, 20.0f, 0); ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); geometry_sink_init(&sink); @@ -5056,7 +5056,7 @@ static void test_rectangle_geometry(BOOL d3d11) rotate_matrix(&matrix, M_PI / -5.0f); hr = ID2D1RectangleGeometry_GetBounds(geometry, &matrix, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 2.00000000e+01f, 1.82442951e+01f, 7.95376282e+01f, 6.23606796e+01f, 0); + match = compare_rect_f(&rect, 2.00000000e+01f, 1.82442951e+01f, 7.95376282e+01f, 6.23606796e+01f, 0); ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); geometry_sink_init(&sink); @@ -5071,7 +5071,7 @@ static void test_rectangle_geometry(BOOL d3d11) scale_matrix(&matrix, 0.0f, 2.0f); hr = ID2D1RectangleGeometry_GetBounds(geometry, &matrix, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 25.0f, 15.0f, 25.0f, 55.0f, 0); + match = compare_rect_f(&rect, 25.0f, 15.0f, 25.0f, 55.0f, 0); ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); geometry_sink_init(&sink); @@ -5086,7 +5086,7 @@ static void test_rectangle_geometry(BOOL d3d11) scale_matrix(&matrix, 0.5f, 0.0f); hr = ID2D1RectangleGeometry_GetBounds(geometry, &matrix, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 30.0f, 45.0f, 35.0f, 45.0f, 0); + match = compare_rect_f(&rect, 30.0f, 45.0f, 35.0f, 45.0f, 0); ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); geometry_sink_init(&sink); @@ -5105,7 +5105,7 @@ static void test_rectangle_geometry(BOOL d3d11) hr = ID2D1TransformedGeometry_GetBounds(transformed_geometry, NULL, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, -7.85640717e+01f, 1.79903809e+02f, 1.07179594e+01f, 2.73205078e+02f, 1); + match = compare_rect_f(&rect, -7.85640717e+01f, 1.79903809e+02f, 1.07179594e+01f, 2.73205078e+02f, 1); ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); geometry_sink_init(&sink); @@ -5126,7 +5126,7 @@ static void test_rectangle_geometry(BOOL d3d11) scale_matrix(&matrix, 0.25f, 0.2f); hr = ID2D1TransformedGeometry_GetBounds(transformed_geometry, &matrix, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 30.0f, 20.0f, 40.0f, 40.0f, 2); + match = compare_rect_f(&rect, 30.0f, 20.0f, 40.0f, 40.0f, 2); ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); geometry_sink_init(&sink); @@ -5140,7 +5140,7 @@ static void test_rectangle_geometry(BOOL d3d11) scale_matrix(&matrix, 2.0f, 0.0f); hr = ID2D1TransformedGeometry_GetBounds(transformed_geometry, &matrix, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, -1.57128143e+02f, 0.00000000e+00f, 2.14359188e+01f, 0.00000000e+00f, 1); + match = compare_rect_f(&rect, -1.57128143e+02f, 0.00000000e+00f, 2.14359188e+01f, 0.00000000e+00f, 1); ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); geometry_sink_init(&sink); @@ -5154,7 +5154,7 @@ static void test_rectangle_geometry(BOOL d3d11) scale_matrix(&matrix, 0.0f, 0.5f); hr = ID2D1TransformedGeometry_GetBounds(transformed_geometry, &matrix, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 0.00000000e+00f, 8.99519043e+01f, 0.00000000e+00, 1.36602539e+02f, 1); + match = compare_rect_f(&rect, 0.00000000e+00f, 8.99519043e+01f, 0.00000000e+00, 1.36602539e+02f, 1); ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); geometry_sink_init(&sink); @@ -11588,7 +11588,7 @@ static void test_geometry_group(BOOL d3d11) set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f); hr = ID2D1GeometryGroup_GetBounds(group, NULL, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, -2.0f, -2.0f, 1.0f, 2.0f, 0); + match = compare_rect_f(&rect, -2.0f, -2.0f, 1.0f, 2.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -11597,7 +11597,7 @@ static void test_geometry_group(BOOL d3d11) scale_matrix(&matrix, 2.0f, 0.5f); hr = ID2D1GeometryGroup_GetBounds(group, &matrix, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 76.0f, 639.0f, 82.0f, 641.0f, 0); + match = compare_rect_f(&rect, 76.0f, 639.0f, 82.0f, 641.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -11614,7 +11614,7 @@ static void test_geometry_group(BOOL d3d11) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); hr = ID2D1GeometryGroup_GetBounds(group, NULL, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, INFINITY, INFINITY, FLT_MAX, FLT_MAX, 0); + match = compare_rect_f(&rect, INFINITY, INFINITY, FLT_MAX, FLT_MAX, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -11632,7 +11632,7 @@ static void test_geometry_group(BOOL d3d11) hr = ID2D1GeometryGroup_GetBounds(group, NULL, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, INFINITY, INFINITY, FLT_MAX, FLT_MAX, 0); + match = compare_rect_f(&rect, INFINITY, INFINITY, FLT_MAX, FLT_MAX, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -11642,7 +11642,7 @@ static void test_geometry_group(BOOL d3d11) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); hr = ID2D1GeometryGroup_GetBounds(group, NULL, &rect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&rect, 160.0f, 240.0f, 240.0f, 720.0f, 0); + match = compare_rect_f(&rect, 160.0f, 240.0f, 240.0f, 720.0f, 0); ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom); @@ -13489,7 +13489,7 @@ static void test_effect_2d_affine(BOOL d3d11) todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); todo_wine - ok(compare_rect(&output_bounds, test->bounds.left, test->bounds.top, test->bounds.right, test->bounds.bottom, 1), + ok(compare_rect_f(&output_bounds, test->bounds.left, test->bounds.top, test->bounds.right, test->bounds.bottom, 1), "Got unexpected output bounds {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", output_bounds.left, output_bounds.top, output_bounds.right, output_bounds.bottom, test->bounds.left, test->bounds.top, test->bounds.right, test->bounds.bottom); @@ -13628,7 +13628,7 @@ static void test_effect_crop(BOOL d3d11) todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); todo_wine - ok(compare_rect(&output_bounds, test->bounds.left, test->bounds.top, test->bounds.right, test->bounds.bottom, 0), + ok(compare_rect_f(&output_bounds, test->bounds.left, test->bounds.top, test->bounds.right, test->bounds.bottom, 0), "Got unexpected output bounds {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", output_bounds.left, output_bounds.top, output_bounds.right, output_bounds.bottom, test->bounds.left, test->bounds.top, test->bounds.right, test->bounds.bottom); @@ -14084,7 +14084,7 @@ static void test_effect_flood(BOOL d3d11) todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); todo_wine - ok(compare_rect(&bounds, -bound, -bound, bound, bound, 0), + ok(compare_rect_f(&bounds, -bound, -bound, bound, bound, 0), "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n", bounds.left, bounds.top, bounds.right, bounds.bottom); @@ -15441,7 +15441,7 @@ static void test_image_bounds(BOOL d3d11) size = ID2D1Bitmap_GetSize(bitmap); hr = ID2D1DeviceContext_GetImageLocalBounds(context, (ID2D1Image *)bitmap, &bounds); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - ok(compare_rect(&bounds, 0.0f, 0.0f, size.width, size.height, 0), + ok(compare_rect_f(&bounds, 0.0f, 0.0f, size.width, size.height, 0), "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", bounds.left, bounds.top, bounds.right, bounds.bottom, 0.0f, 0.0f, size.width, size.height); @@ -15450,7 +15450,7 @@ static void test_image_bounds(BOOL d3d11) ID2D1DeviceContext_SetDpi(context, dpi_x * 2.0f, dpi_y * 2.0f); hr = ID2D1DeviceContext_GetImageLocalBounds(context, (ID2D1Image *)bitmap, &bounds); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - ok(compare_rect(&bounds, 0.0f, 0.0f, size.width, size.height, 0), + ok(compare_rect_f(&bounds, 0.0f, 0.0f, size.width, size.height, 0), "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", bounds.left, bounds.top, bounds.right, bounds.bottom, 0.0f, 0.0f, size.width, size.height); ID2D1DeviceContext_SetDpi(context, dpi_x, dpi_y); @@ -15461,7 +15461,7 @@ static void test_image_bounds(BOOL d3d11) ID2D1DeviceContext_SetUnitMode(context, D2D1_UNIT_MODE_PIXELS); hr = ID2D1DeviceContext_GetImageLocalBounds(context, (ID2D1Image *)bitmap, &bounds); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - ok(compare_rect(&bounds, 0.0f, 0.0f, test->pixel_size.width, test->pixel_size.height, 0), + ok(compare_rect_f(&bounds, 0.0f, 0.0f, test->pixel_size.width, test->pixel_size.height, 0), "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", bounds.left, bounds.top, bounds.right, bounds.bottom, 0.0f, 0.0f, (float)test->pixel_size.width, (float)test->pixel_size.height); @@ -17808,7 +17808,7 @@ static void test_transformed_geometry(BOOL d3d11) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); if (hr == S_OK) { - match = compare_rect(&bounds, INFINITY, INFINITY, FLT_MAX, FLT_MAX, 0); + match = compare_rect_f(&bounds, INFINITY, INFINITY, FLT_MAX, FLT_MAX, 0); ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n", bounds.left, bounds.top, bounds.right, bounds.bottom); } @@ -17819,7 +17819,7 @@ static void test_transformed_geometry(BOOL d3d11) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); if (hr == S_OK) { - match = compare_rect(&bounds, INFINITY, INFINITY, FLT_MAX, FLT_MAX, 0); + match = compare_rect_f(&bounds, INFINITY, INFINITY, FLT_MAX, FLT_MAX, 0); ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n", bounds.left, bounds.top, bounds.right, bounds.bottom); } @@ -17827,7 +17827,7 @@ static void test_transformed_geometry(BOOL d3d11) set_rect(&bounds, 1.0f, 2.0f, 3.0f, 4.0f); hr = ID2D1PathGeometry_GetBounds(path_geometry, NULL, &bounds); ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&bounds, 1.0f, 2.0f, 3.0f, 4.0f, 0); + match = compare_rect_f(&bounds, 1.0f, 2.0f, 3.0f, 4.0f, 0); ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n", bounds.left, bounds.top, bounds.right, bounds.bottom); @@ -17865,14 +17865,14 @@ static void test_transformed_geometry(BOOL d3d11) set_rect(&bounds, 1.0f, 2.0f, 3.0f, 4.0f); hr = ID2D1TransformedGeometry_GetBounds(geometry, NULL, &bounds); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&bounds, 240.0f, 720.0f, 250.0f, 730.0f, 0); + match = compare_rect_f(&bounds, 240.0f, 720.0f, 250.0f, 730.0f, 0); ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n", bounds.left, bounds.top, bounds.right, bounds.bottom); set_rect(&bounds, 1.0f, 2.0f, 3.0f, 4.0f); hr = ID2D1TransformedGeometry_GetBounds(geometry2, NULL, &bounds); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - match = compare_rect(&bounds, 720.0f, 2160.0f, 730.0f, 2170.0f, 0); + match = compare_rect_f(&bounds, 720.0f, 2160.0f, 730.0f, 2170.0f, 0); ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n", bounds.left, bounds.top, bounds.right, bounds.bottom); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11249
From: Santino Mazza <smazza@codeweavers.com> --- dlls/d2d1/Makefile.in | 1 + dlls/d2d1/d2d1_private.h | 8 + dlls/d2d1/device.c | 8 +- dlls/d2d1/sprite_batch.c | 141 +++++++++++++++++ dlls/d2d1/tests/d2d1.c | 333 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 489 insertions(+), 2 deletions(-) create mode 100644 dlls/d2d1/sprite_batch.c diff --git a/dlls/d2d1/Makefile.in b/dlls/d2d1/Makefile.in index 7c4596462aa..73add39286b 100644 --- a/dlls/d2d1/Makefile.in +++ b/dlls/d2d1/Makefile.in @@ -19,6 +19,7 @@ SOURCES = \ hwnd_render_target.c \ layer.c \ mesh.c \ + sprite_batch.c \ state_block.c \ stroke.c \ wic_render_target.c diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index 9c78aaf92e2..a54077f8f98 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -460,6 +460,14 @@ HRESULT d2d_bitmap_create_from_wic_bitmap(struct d2d_device_context *context, IW unsigned int d2d_get_bitmap_options_for_surface(IDXGISurface *surface); struct d2d_bitmap *unsafe_impl_from_ID2D1Bitmap(ID2D1Bitmap *iface); +struct d2d_sprite_batch { + ID2D1SpriteBatch ID2D1SpriteBatch_iface; + + LONG refcount; +}; + +HRESULT d2d_create_sprite_batch(struct d2d_device_context *ctx, ID2D1SpriteBatch **iface); + struct d2d_state_block { ID2D1DrawingStateBlock1 ID2D1DrawingStateBlock1_iface; diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index b3560f09c12..0082288b4e9 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -3037,9 +3037,13 @@ static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateTransformedImageSource static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSpriteBatch(ID2D1DeviceContext6 *iface, ID2D1SpriteBatch **sprite_batch) { - FIXME("iface %p, sprite_batch %p stub!\n", iface, sprite_batch); + struct d2d_device_context *ctx = impl_from_ID2D1DeviceContext(iface); + TRACE("iface %p, sprite_batch %p\n", iface, sprite_batch); - return E_NOTIMPL; + if (!sprite_batch) + return E_INVALIDARG; + + return d2d_create_sprite_batch(ctx, sprite_batch); } static void STDMETHODCALLTYPE d2d_device_context_DrawSpriteBatch(ID2D1DeviceContext6 *iface, diff --git a/dlls/d2d1/sprite_batch.c b/dlls/d2d1/sprite_batch.c new file mode 100644 index 00000000000..e5d8c0c88a6 --- /dev/null +++ b/dlls/d2d1/sprite_batch.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Santino Mazza for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "d2d1_private.h" +#include <windows.h> + +WINE_DEFAULT_DEBUG_CHANNEL(d2d); + +static inline struct d2d_sprite_batch *impl_from_ID2D1SpriteBatch(ID2D1SpriteBatch *iface) +{ + return CONTAINING_RECORD(iface, struct d2d_sprite_batch, ID2D1SpriteBatch_iface); +} + +static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_QueryInterface(ID2D1SpriteBatch *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_ID2D1SpriteBatch) + || IsEqualGUID(iid, &IID_IUnknown)) + { + ID2D1SpriteBatch_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE d2d_sprite_batch_AddRef(ID2D1SpriteBatch *iface) +{ + struct d2d_sprite_batch *batch = impl_from_ID2D1SpriteBatch(iface); + ULONG refcount = InterlockedIncrement(&batch->refcount); + + TRACE("%p increasing refcount to %lu.\n", iface, refcount); + + return refcount; +} + +static ULONG STDMETHODCALLTYPE d2d_sprite_batch_Release(ID2D1SpriteBatch *iface) +{ + struct d2d_sprite_batch *batch = impl_from_ID2D1SpriteBatch(iface); + ULONG refcount = InterlockedDecrement(&batch->refcount); + + TRACE("%p decreasing refcount to %lu.\n", iface, refcount); + + if (!refcount) { + free(batch); + } + + return refcount; +} + +static void STDMETHODCALLTYPE d2d_sprite_batch_GetFactory(ID2D1SpriteBatch *iface, ID2D1Factory **factory) +{ + FIXME("(%p): stub\n", iface); +} + +static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_AddSprites(ID2D1SpriteBatch *iface, UINT32 sprite_count, + const D2D1_RECT_F *destination_rectangles, const D2D1_RECT_U *source_rectangles, const D2D1_COLOR_F *colors, + const D2D1_MATRIX_3X2_F *transforms, UINT32 destination_rectangles_stride, UINT32 source_rectangles_stride, + UINT32 colors_stride, UINT32 transforms_stride) +{ + FIXME("(%p): stub\n", iface); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_SetSprites(ID2D1SpriteBatch *iface, UINT32 start_index, UINT32 sprite_count, + const D2D1_RECT_F *destination_rectangles, const D2D1_RECT_U *source_rectangles, const D2D1_COLOR_F *colors, + const D2D1_MATRIX_3X2_F *transforms, UINT32 destination_rectangles_stride, UINT32 source_rectangles_stride, + UINT32 colors_stride, UINT32 transforms_stride) +{ + FIXME("(%p): stub\n", iface); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_GetSprites(ID2D1SpriteBatch *iface, UINT32 start_index, UINT32 sprite_count, + D2D1_RECT_F *destination_rectangles, D2D1_RECT_U *source_rectangles, D2D1_COLOR_F *colors, + D2D1_MATRIX_3X2_F *transforms) +{ + FIXME("(%p): stub\n", iface); + + return E_NOTIMPL; +} + +static UINT32 STDMETHODCALLTYPE d2d_sprite_batch_GetSpritesCount(ID2D1SpriteBatch *iface) +{ + FIXME("(%p): stub\n", iface); + + return 0; +} + +static void STDMETHODCALLTYPE d2d_sprite_batch_Clear(ID2D1SpriteBatch *iface) +{ + FIXME("(%p): stub\n", iface); +} + +static const struct ID2D1SpriteBatchVtbl d2d_sprite_batch_vtbl = { + d2d_sprite_batch_QueryInterface, + d2d_sprite_batch_AddRef, + d2d_sprite_batch_Release, + d2d_sprite_batch_GetFactory, + d2d_sprite_batch_AddSprites, + d2d_sprite_batch_SetSprites, + d2d_sprite_batch_GetSprites, + d2d_sprite_batch_GetSpritesCount, + d2d_sprite_batch_Clear +}; + +HRESULT d2d_create_sprite_batch(struct d2d_device_context *ctx, ID2D1SpriteBatch **iface) { + struct d2d_sprite_batch *sprite_batch; + + if (!(sprite_batch = calloc(1, sizeof(*sprite_batch)))) + return E_OUTOFMEMORY; + + sprite_batch->ID2D1SpriteBatch_iface.lpVtbl = &d2d_sprite_batch_vtbl; + + ID2D1SpriteBatch_AddRef(&sprite_batch->ID2D1SpriteBatch_iface); + *iface = &sprite_batch->ID2D1SpriteBatch_iface; + + return S_OK; +} diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index afda90f1271..7404c3aa2a4 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -909,6 +909,14 @@ static BOOL compare_rect_f(const D2D1_RECT_F *rect, float left, float top, float && compare_float(rect->bottom, bottom, ulps); } +static BOOL compare_rect_u(const D2D1_RECT_U *rect, UINT left, UINT top, UINT right, UINT bottom) +{ + return rect->left == left && + rect->top == top && + rect->right == right && + rect->bottom == bottom; +} + static BOOL compare_bezier_segment(const D2D1_BEZIER_SEGMENT *b, float x1, float y1, float x2, float y2, float x3, float y3, unsigned int ulps) { @@ -18004,6 +18012,330 @@ static void test_glyph_run_world_bounds(BOOL d3d11) release_test_context(&ctx); } +static void test_sprite_batches(BOOL d3d11) { + ID2D1SpriteBatch *sprite_batch; + struct d2d1_test_context ctx; + ID2D1DeviceContext3 *device; + ID2D1Bitmap *bitmap; + UINT32 sprite_count; + BOOL check; + HRESULT hr; + + static const DWORD bitmap_data[] = + { + 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff, + 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f, + 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, + 0xffffffff, 0xff000000, 0xff000000, 0xff000000, + }; + const D2D1_SIZE_U bitmap_size = {4, 4}; + const D2D1_BITMAP_PROPERTIES bitmap_desc = { + {DXGI_FORMAT_B8G8R8A8_UNORM, + D2D1_ALPHA_MODE_IGNORE}, + 96.0f, + 96.0f + }; + + D2D1_RECT_F test_destination_rect[2] = {{0, 0, bitmap_size.width, bitmap_size.height}, {5, 5, 9, 9}}; + D2D1_RECT_U test_source_rect[2] = {{0, 0, 4, 4}, {1, 1, 4, 4}}; + D2D1_COLOR_F test_colors[2] = {{1.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}; + D2D1_MATRIX_3X2_F test_matrixes[2]; + + D2D1_RECT_F destination_rects[4]; + D2D1_RECT_U source_rects[4]; + D2D1_COLOR_F colors[4]; + D2D1_MATRIX_3X2_F transforms[4]; + + set_matrix_identity(&test_matrixes[0]); + set_matrix_identity(&test_matrixes[1]); + + if (!init_test_context(&ctx, d3d11)) + return; + + hr = ID2D1DeviceContext_QueryInterface(ctx.context, &IID_ID2D1DeviceContext3, (void**)&device); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + hr = ID2D1DeviceContext3_CreateSpriteBatch(device, &sprite_batch); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + todo_wine check_interface(sprite_batch, &IID_ID2D1Resource, TRUE); + + hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, NULL, NULL, NULL, NULL, 0, 0, 0, 0); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); + ok(sprite_count == 0, "Expected sprite count of 0 got %d\n", sprite_count); + + hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, NULL, test_source_rect, NULL, NULL, 0, 0, 0, 0); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); + ok(sprite_count == 0, "Expected sprite count of 0 got %d\n", sprite_count); + + hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, test_destination_rect, NULL, NULL, NULL, 0, 0, 0, 0); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); + todo_wine ok(sprite_count == 2, "Expected sprite count of 2 got %d\n", sprite_count); + + hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 2, destination_rects, source_rects, colors, transforms); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + todo_wine ok(compare_rect_f(&destination_rects[0], 0, 0, 4, 4, 0), + "Got unexpected rectangle {%f, %f, %f, %f}.\n", + destination_rects[0].left, destination_rects[0].top, + destination_rects[0].right, destination_rects[0].bottom); + + todo_wine ok(compare_rect_f(&destination_rects[1], 0, 0, 4, 4, 0), + "Got unexpected rectangle {%f, %f, %f, %f}.\n", + destination_rects[1].left, destination_rects[1].top, + destination_rects[1].right, destination_rects[1].bottom); + + hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, test_destination_rect, NULL, NULL, NULL, sizeof(*test_destination_rect), 0, 0, 0); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + + sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); + todo_wine ok(sprite_count == 4, "Expected sprite count of 4 got %d\n", sprite_count); + + hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 4, destination_rects, source_rects, colors, transforms); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + todo_wine ok(compare_rect_f(&destination_rects[0], 0, 0, 4, 4, 0), + "Got unexpected rectangle {%f, %f, %f, %f}.\n", + destination_rects[0].left, destination_rects[0].top, + destination_rects[0].right, destination_rects[0].bottom); + + todo_wine ok(compare_rect_f(&destination_rects[1], 0, 0, 4, 4, 0), + "Got unexpected rectangle {%f, %f, %f, %f}.\n", + destination_rects[1].left, destination_rects[1].top, + destination_rects[1].right, destination_rects[1].bottom); + + todo_wine ok(compare_rect_f(&destination_rects[2], 0, 0, 4, 4, 0), + "Got unexpected rectangle {%f, %f, %f, %f}.\n", + destination_rects[2].left, destination_rects[2].top, + destination_rects[2].right, destination_rects[2].bottom); + + todo_wine ok(compare_rect_f(&destination_rects[3], 5, 5, 9, 9, 0), + "Got unexpected rectangle {%f, %f, %f, %f}.\n", + destination_rects[3].left, destination_rects[3].top, + destination_rects[3].right, destination_rects[3].bottom); + + hr = ID2D1SpriteBatch_SetSprites(sprite_batch, 0, 0, NULL, NULL, NULL, NULL, 0, 0, 0, 0); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + hr = ID2D1SpriteBatch_SetSprites(sprite_batch, 0, 8, NULL, NULL, NULL, NULL, 0, 0, 0, 0); + todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#lx\n", hr); + + hr = ID2D1SpriteBatch_SetSprites(sprite_batch, 5, 1, NULL, NULL, NULL, NULL, 0, 0, 0, 0); + todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#lx\n", hr); + + hr = ID2D1SpriteBatch_SetSprites(sprite_batch, 0, 1, NULL, NULL, NULL, NULL, 0, 0, 0, 0); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + hr = ID2D1SpriteBatch_SetSprites(sprite_batch, 0, 8, &test_destination_rect[1], NULL, NULL, NULL, 0, 0, 0, 0); + todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#lx\n", hr); + + hr = ID2D1SpriteBatch_SetSprites(sprite_batch, 0, 1, &test_destination_rect[1], NULL, NULL, NULL, 0, 0, 0, 0); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 1, destination_rects, NULL, NULL, NULL); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + todo_wine ok(compare_rect_f(&destination_rects[0], 5, 5, 9, 9, 0), + "Got unexpected rectangle {%f, %f, %f, %f}.\n", + destination_rects[0].left, destination_rects[0].top, + destination_rects[0].right, destination_rects[0].bottom); + + ID2D1SpriteBatch_Clear(sprite_batch); + sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); + ok(sprite_count == 0, "Expected sprite count of 0 got %d\n", sprite_count); + + + hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, test_destination_rect, NULL, NULL, NULL, sizeof(test_destination_rect->top), 0, 0, 0); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); + todo_wine ok(sprite_count == 2, "Expected sprite count of 2 got %d\n", sprite_count); + + hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 2, destination_rects, source_rects, colors, transforms); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + todo_wine ok(compare_rect_f(&destination_rects[0], 0, 0, 4, 4, 0), + "Got unexpected rectangle {%f, %f, %f, %f}.\n", + destination_rects[0].left, destination_rects[0].top, + destination_rects[0].right, destination_rects[0].bottom); + + todo_wine ok(compare_rect_f(&destination_rects[1], 0, 4, 4, 5, 0), + "Got unexpected rectangle {%f, %f, %f, %f}.\n", + destination_rects[1].left, destination_rects[1].top, + destination_rects[1].right, destination_rects[1].bottom); + + ID2D1SpriteBatch_Clear(sprite_batch); + sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); + ok(sprite_count == 0, "Expected sprite count of 0 got %d\n", sprite_count); + + + hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, test_destination_rect, NULL, NULL, NULL, sizeof(*test_destination_rect), 0, 0, 0); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); + todo_wine ok(sprite_count == 2, "Expected sprite count of 2 got %d\n", sprite_count); + + hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 4, destination_rects, source_rects, colors, transforms); + todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#lx\n", hr); + + hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 3, 1, destination_rects, source_rects, colors, transforms); + todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#lx\n", hr); + + hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 3, 0, destination_rects, source_rects, colors, transforms); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 0, destination_rects, source_rects, colors, transforms); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 2, NULL, NULL, NULL, NULL); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 2, destination_rects, source_rects, colors, transforms); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 2, NULL, source_rects, NULL, NULL); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + + hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 2, destination_rects, NULL, NULL, NULL); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + todo_wine ok(compare_rect_f(&destination_rects[0], 0, 0, 4, 4, 0), + "Got unexpected rectangle {%f, %f, %f, %f}.\n", + destination_rects[0].left, destination_rects[0].top, + destination_rects[0].right, destination_rects[0].bottom); + + todo_wine ok(compare_rect_f(&destination_rects[1], 5, 5, 9, 9, 0), + "Got unexpected rectangle {%f, %f, %f, %f}.\n", + destination_rects[1].left, destination_rects[1].top, + destination_rects[1].right, destination_rects[1].bottom); + + hr = ID2D1RenderTarget_CreateBitmap(ctx.rt, bitmap_size, bitmap_data, bitmap_size.width * sizeof(*bitmap_data), &bitmap_desc, &bitmap); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + ID2D1DeviceContext3_SetAntialiasMode(device, D2D1_ANTIALIAS_MODE_ALIASED); + + ID2D1DeviceContext3_BeginDraw(device); + ID2D1DeviceContext3_DrawSpriteBatch(device, sprite_batch, 0, 1, bitmap, 0, D2D1_SPRITE_OPTIONS_NONE); + hr = ID2D1DeviceContext3_EndDraw(device, 0, 0); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + check = compare_surface(&ctx, "5e8144c13d1a71f0b59d54eba7156218693fa7bd"); + todo_wine ok(check, "Surface does not match.\n"); + + ID2D1DeviceContext3_BeginDraw(device); + ID2D1DeviceContext3_DrawSpriteBatch(device, sprite_batch, 0, 2, bitmap, 0, D2D1_SPRITE_OPTIONS_NONE); + hr = ID2D1DeviceContext3_EndDraw(device, 0, 0); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + check = compare_surface(&ctx, "064e9e8b46799904cab52b14d69a235d4f41409b"); + todo_wine ok(check, "Surface does not match.\n"); + + ID2D1SpriteBatch_Clear(sprite_batch); + sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); + ok(sprite_count == 0, "Expected sprite count of 0 got %d\n", sprite_count); + + hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, test_destination_rect, test_source_rect, NULL, NULL, sizeof(*test_destination_rect), sizeof(*test_source_rect), 0, 0); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 2, destination_rects, source_rects, NULL, NULL); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + todo_wine ok(compare_rect_f(&destination_rects[0], 0, 0, 4, 4, 0), + "Got unexpected rectangle {%f, %f, %f, %f}.\n", + destination_rects[0].left, destination_rects[0].top, + destination_rects[0].right, destination_rects[0].bottom); + + todo_wine ok(compare_rect_f(&destination_rects[1], 5, 5, 9, 9, 0), + "Got unexpected rectangle {%f, %f, %f, %f}.\n", + destination_rects[1].left, destination_rects[1].top, + destination_rects[1].right, destination_rects[1].bottom); + + todo_wine ok(compare_rect_u(&source_rects[0], 0, 0, 4, 4), + "Got unexpected rectangle {%u, %u, %u, %u}.\n", + source_rects[0].left, source_rects[0].top, + source_rects[0].right, source_rects[0].bottom); + + todo_wine ok(compare_rect_u(&source_rects[1], 1, 1, 4, 4), + "Got unexpected rectangle {%u, %u, %u, %u}.\n", + source_rects[1].left, source_rects[1].top, + source_rects[1].right, source_rects[1].bottom); + + ID2D1DeviceContext3_BeginDraw(device); + ID2D1DeviceContext3_DrawSpriteBatch(device, sprite_batch, 0, 2, bitmap, 0, D2D1_SPRITE_OPTIONS_NONE); + hr = ID2D1DeviceContext3_EndDraw(device, 0, 0); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + check = compare_surface(&ctx, "9133aab139f4c0ec2edea7e3c63069370ff88083"); + todo_wine ok(check, "Surface does not match.\n"); + + + ID2D1SpriteBatch_Clear(sprite_batch); + sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); + ok(sprite_count == 0, "Expected sprite count of 0 got %d\n", sprite_count); + + set_matrix_identity(&test_matrixes[1]); + scale_matrix(&test_matrixes[1], 4.0f, 4.0f); + hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, test_destination_rect, test_source_rect, NULL, test_matrixes, sizeof(*test_destination_rect), sizeof(*test_source_rect), 0, sizeof(D2D1_MATRIX_3X2_F)); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + ID2D1DeviceContext3_BeginDraw(device); + ID2D1DeviceContext3_DrawSpriteBatch(device, sprite_batch, 0, 2, bitmap, 0, D2D1_SPRITE_OPTIONS_NONE); + hr = ID2D1DeviceContext3_EndDraw(device, 0, 0); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + check = compare_surface(&ctx, "30bf2de6f4f10ae8ebfc61261ad0d0a4abfed094"); + todo_wine ok(check, "Surface does not match.\n"); + + + ID2D1SpriteBatch_Clear(sprite_batch); + sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); + ok(sprite_count == 0, "Expected sprite count of 0 got %d\n", sprite_count); + + hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, test_destination_rect, test_source_rect, test_colors, NULL, sizeof(*test_destination_rect), sizeof(*test_source_rect), sizeof(D2D1_COLOR_F), 0); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + ID2D1DeviceContext3_BeginDraw(device); + ID2D1DeviceContext3_DrawSpriteBatch(device, sprite_batch, 0, 2, bitmap, 0, D2D1_SPRITE_OPTIONS_NONE); + hr = ID2D1DeviceContext3_EndDraw(device, 0, 0); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + check = compare_surface(&ctx, "e21f4ac578dcc4ed266959872d243a8ce4f493d7"); + todo_wine ok(check, "Surface does not match.\n"); + + + ID2D1SpriteBatch_Clear(sprite_batch); + sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); + ok(sprite_count == 0, "Expected sprite count of 0 got %d\n", sprite_count); + + set_matrix_identity(&test_matrixes[1]); + skew_matrix(&test_matrixes[1], 0.5f, 0.5f); + hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, test_destination_rect, test_source_rect, NULL, test_matrixes, sizeof(*test_destination_rect), sizeof(*test_source_rect), 0, sizeof(D2D1_MATRIX_3X2_F)); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + + ID2D1DeviceContext3_BeginDraw(device); + ID2D1DeviceContext3_DrawSpriteBatch(device, sprite_batch, 0, 2, bitmap, 0, D2D1_SPRITE_OPTIONS_NONE); + hr = ID2D1DeviceContext3_EndDraw(device, 0, 0); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + check = compare_surface(&ctx, "72d4c7723073eabc2d7d1939b6f41040546b21f7"); + todo_wine ok(check, "Surface does not match.\n"); + + ID2D1DeviceContext3_SetAntialiasMode(device, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); + + ID2D1DeviceContext3_BeginDraw(device); + ID2D1DeviceContext3_DrawSpriteBatch(device, sprite_batch, 0, 2, bitmap, 0, D2D1_SPRITE_OPTIONS_NONE); + hr = ID2D1DeviceContext3_EndDraw(device, 0, 0); + todo_wine ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr); + + ID2D1Bitmap_Release(bitmap); + + ID2D1DeviceContext3_Release(device); + ID2D1SpriteBatch_Release(sprite_batch); + release_test_context(&ctx); +} + START_TEST(d2d1) { HMODULE d2d1_dll = GetModuleHandleA("d2d1.dll"); @@ -18127,6 +18459,7 @@ START_TEST(d2d1) queue_d3d10_test(test_path_geometry_stream); queue_d3d10_test(test_transformed_geometry); queue_d3d10_test(test_glyph_run_world_bounds); + queue_test(test_sprite_batches); run_queued_tests(); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11249
From: Santino Mazza <smazza@codeweavers.com> --- dlls/d2d1/d2d1_private.h | 6 +++ dlls/d2d1/device.c | 10 +++- dlls/d2d1/sprite_batch.c | 105 +++++++++++++++++++++++++++++++++++---- dlls/d2d1/tests/d2d1.c | 98 ++++++++++++++++++------------------ 4 files changed, 157 insertions(+), 62 deletions(-) diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index a54077f8f98..54ae00c6ac6 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -463,10 +463,16 @@ struct d2d_bitmap *unsafe_impl_from_ID2D1Bitmap(ID2D1Bitmap *iface); struct d2d_sprite_batch { ID2D1SpriteBatch ID2D1SpriteBatch_iface; + ID2D1Factory *factory; LONG refcount; + + UINT32 sprite_count; + UINT32 sprites_allocated; + D2D1_RECT_F *destination_rectangles; }; HRESULT d2d_create_sprite_batch(struct d2d_device_context *ctx, ID2D1SpriteBatch **iface); +struct d2d_sprite_batch *unsafe_impl_from_ID2D1SpriteBatch(ID2D1SpriteBatch *iface); struct d2d_state_block { diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index 0082288b4e9..c0322870692 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -3050,9 +3050,15 @@ static void STDMETHODCALLTYPE d2d_device_context_DrawSpriteBatch(ID2D1DeviceCont ID2D1SpriteBatch *sprite_batch, UINT32 start_index, UINT32 sprite_count, ID2D1Bitmap *bitmap, D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, D2D1_SPRITE_OPTIONS sprite_options) { - FIXME("iface %p, sprite_batch %p, start_index %u, sprite_count %u, bitmap %p, interpolation_mode %u," - "sprite_options %u stub!\n", iface, sprite_batch, start_index, sprite_count, bitmap, + struct d2d_sprite_batch *sprite_batch_impl = unsafe_impl_from_ID2D1SpriteBatch(sprite_batch); + TRACE("iface %p, sprite_batch %p, start_index %u, sprite_count %u, bitmap %p, interpolation_mode %u," + "sprite_options %u\n", iface, sprite_batch, start_index, sprite_count, bitmap, interpolation_mode, sprite_options); + + for (int i = start_index; i < start_index + sprite_count; ++i) { + ID2D1DeviceContext6_DrawBitmap(iface, bitmap, &sprite_batch_impl->destination_rectangles[i], 1.0f, + (D2D1_INTERPOLATION_MODE)interpolation_mode, 0, 0); + } } static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSvgGlyphStyle(ID2D1DeviceContext6 *iface, diff --git a/dlls/d2d1/sprite_batch.c b/dlls/d2d1/sprite_batch.c index e5d8c0c88a6..667501ffb84 100644 --- a/dlls/d2d1/sprite_batch.c +++ b/dlls/d2d1/sprite_batch.c @@ -31,6 +31,7 @@ static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_QueryInterface(ID2D1SpriteBatc TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); if (IsEqualGUID(iid, &IID_ID2D1SpriteBatch) + || IsEqualGUID(iid, &IID_ID2D1Resource) || IsEqualGUID(iid, &IID_IUnknown)) { ID2D1SpriteBatch_AddRef(iface); @@ -62,6 +63,8 @@ static ULONG STDMETHODCALLTYPE d2d_sprite_batch_Release(ID2D1SpriteBatch *iface) TRACE("%p decreasing refcount to %lu.\n", iface, refcount); if (!refcount) { + ID2D1Factory_Release(batch->factory); + free(batch->destination_rectangles); free(batch); } @@ -70,7 +73,12 @@ static ULONG STDMETHODCALLTYPE d2d_sprite_batch_Release(ID2D1SpriteBatch *iface) static void STDMETHODCALLTYPE d2d_sprite_batch_GetFactory(ID2D1SpriteBatch *iface, ID2D1Factory **factory) { - FIXME("(%p): stub\n", iface); + struct d2d_sprite_batch *batch = impl_from_ID2D1SpriteBatch(iface); + + TRACE("iface %p, factory %p.\n", iface, factory); + + *factory = batch->factory; + ID2D1Factory_AddRef(*factory); } static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_AddSprites(ID2D1SpriteBatch *iface, UINT32 sprite_count, @@ -78,9 +86,34 @@ static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_AddSprites(ID2D1SpriteBatch *i const D2D1_MATRIX_3X2_F *transforms, UINT32 destination_rectangles_stride, UINT32 source_rectangles_stride, UINT32 colors_stride, UINT32 transforms_stride) { - FIXME("(%p): stub\n", iface); + struct d2d_sprite_batch *batch = impl_from_ID2D1SpriteBatch(iface); + + TRACE("(%p)\n", iface); + + if (!destination_rectangles) + return S_OK; + + if (source_rectangles) + FIXME("Source rectangles not implemented.\n"); + + if (colors) + FIXME("Color mask not implemented\n"); + + if (transforms) + FIXME("Transform matrixes not implemented.\n"); + + if (batch->sprites_allocated <= batch->sprite_count + sprite_count) + { + batch->sprites_allocated = max(batch->sprites_allocated + sprite_count, batch->sprites_allocated * 2); + batch->destination_rectangles = realloc(batch->destination_rectangles, sizeof(D2D1_RECT_F) * batch->sprites_allocated); + } + + for (int i = 0; i < sprite_count; ++i) + batch->destination_rectangles[i + batch->sprite_count] = *(D2D1_RECT_F *)(((UCHAR*)destination_rectangles) + i * destination_rectangles_stride); - return E_NOTIMPL; + batch->sprite_count += sprite_count; + + return S_OK; } static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_SetSprites(ID2D1SpriteBatch *iface, UINT32 start_index, UINT32 sprite_count, @@ -88,30 +121,66 @@ static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_SetSprites(ID2D1SpriteBatch *i const D2D1_MATRIX_3X2_F *transforms, UINT32 destination_rectangles_stride, UINT32 source_rectangles_stride, UINT32 colors_stride, UINT32 transforms_stride) { - FIXME("(%p): stub\n", iface); + struct d2d_sprite_batch *batch = impl_from_ID2D1SpriteBatch(iface); + + TRACE("(%p)\n", iface); + + if (!sprite_count) + return S_OK; + + if (start_index >= batch->sprite_count || sprite_count > batch->sprite_count - start_index) + return E_INVALIDARG; + + if (colors) + FIXME("Color mask not implemented\n"); - return E_NOTIMPL; + if (source_rectangles) + FIXME("Source rectangles not implemented\n"); + + if (transforms) + FIXME("Transform matrixes not implemented\n"); + + for (int i = start_index; i < start_index + sprite_count; ++i) + { + if (destination_rectangles) + batch->destination_rectangles[i] = *(D2D1_RECT_F *)(((UCHAR*)destination_rectangles) + i * destination_rectangles_stride); + } + + return S_OK; } static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_GetSprites(ID2D1SpriteBatch *iface, UINT32 start_index, UINT32 sprite_count, D2D1_RECT_F *destination_rectangles, D2D1_RECT_U *source_rectangles, D2D1_COLOR_F *colors, D2D1_MATRIX_3X2_F *transforms) { - FIXME("(%p): stub\n", iface); + struct d2d_sprite_batch *batch = impl_from_ID2D1SpriteBatch(iface); + TRACE("(%p)\n", iface); + + if (!sprite_count) + return S_OK; + + if (start_index >= batch->sprite_count || sprite_count > batch->sprite_count - start_index) + return E_INVALIDARG; + + if (destination_rectangles) + memcpy(destination_rectangles, &batch->destination_rectangles[start_index], sizeof(D2D1_RECT_F) * sprite_count); - return E_NOTIMPL; + return S_OK; } static UINT32 STDMETHODCALLTYPE d2d_sprite_batch_GetSpritesCount(ID2D1SpriteBatch *iface) { - FIXME("(%p): stub\n", iface); - - return 0; + struct d2d_sprite_batch *batch = impl_from_ID2D1SpriteBatch(iface); + TRACE("(%p)\n", iface); + return batch->sprite_count; } static void STDMETHODCALLTYPE d2d_sprite_batch_Clear(ID2D1SpriteBatch *iface) { - FIXME("(%p): stub\n", iface); + struct d2d_sprite_batch *batch = impl_from_ID2D1SpriteBatch(iface); + TRACE("(%p)\n", iface); + + batch->sprite_count = 0; } static const struct ID2D1SpriteBatchVtbl d2d_sprite_batch_vtbl = { @@ -134,8 +203,22 @@ HRESULT d2d_create_sprite_batch(struct d2d_device_context *ctx, ID2D1SpriteBatch sprite_batch->ID2D1SpriteBatch_iface.lpVtbl = &d2d_sprite_batch_vtbl; + sprite_batch->sprites_allocated = 1; + sprite_batch->destination_rectangles = calloc(sprite_batch->sprites_allocated, sizeof(D2D1_RECT_F)); + + ID2D1Factory_AddRef(ctx->factory); + sprite_batch->factory = ctx->factory; + ID2D1SpriteBatch_AddRef(&sprite_batch->ID2D1SpriteBatch_iface); *iface = &sprite_batch->ID2D1SpriteBatch_iface; return S_OK; } + +struct d2d_sprite_batch *unsafe_impl_from_ID2D1SpriteBatch(ID2D1SpriteBatch *iface) +{ + if (!iface) + return NULL; + assert(iface->lpVtbl == (ID2D1SpriteBatchVtbl *)&d2d_sprite_batch_vtbl); + return CONTAINING_RECORD(iface, struct d2d_sprite_batch, ID2D1SpriteBatch_iface); +} diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 7404c3aa2a4..11d8c6966ca 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -18058,91 +18058,91 @@ static void test_sprite_batches(BOOL d3d11) { hr = ID2D1DeviceContext3_CreateSpriteBatch(device, &sprite_batch); ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); - todo_wine check_interface(sprite_batch, &IID_ID2D1Resource, TRUE); + check_interface(sprite_batch, &IID_ID2D1Resource, TRUE); hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, NULL, NULL, NULL, NULL, 0, 0, 0, 0); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); ok(sprite_count == 0, "Expected sprite count of 0 got %d\n", sprite_count); hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, NULL, test_source_rect, NULL, NULL, 0, 0, 0, 0); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); ok(sprite_count == 0, "Expected sprite count of 0 got %d\n", sprite_count); hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, test_destination_rect, NULL, NULL, NULL, 0, 0, 0, 0); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); - todo_wine ok(sprite_count == 2, "Expected sprite count of 2 got %d\n", sprite_count); + ok(sprite_count == 2, "Expected sprite count of 2 got %d\n", sprite_count); hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 2, destination_rects, source_rects, colors, transforms); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); - todo_wine ok(compare_rect_f(&destination_rects[0], 0, 0, 4, 4, 0), + ok(compare_rect_f(&destination_rects[0], 0, 0, 4, 4, 0), "Got unexpected rectangle {%f, %f, %f, %f}.\n", destination_rects[0].left, destination_rects[0].top, destination_rects[0].right, destination_rects[0].bottom); - todo_wine ok(compare_rect_f(&destination_rects[1], 0, 0, 4, 4, 0), + ok(compare_rect_f(&destination_rects[1], 0, 0, 4, 4, 0), "Got unexpected rectangle {%f, %f, %f, %f}.\n", destination_rects[1].left, destination_rects[1].top, destination_rects[1].right, destination_rects[1].bottom); hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, test_destination_rect, NULL, NULL, NULL, sizeof(*test_destination_rect), 0, 0, 0); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); - todo_wine ok(sprite_count == 4, "Expected sprite count of 4 got %d\n", sprite_count); + ok(sprite_count == 4, "Expected sprite count of 4 got %d\n", sprite_count); hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 4, destination_rects, source_rects, colors, transforms); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); - todo_wine ok(compare_rect_f(&destination_rects[0], 0, 0, 4, 4, 0), + ok(compare_rect_f(&destination_rects[0], 0, 0, 4, 4, 0), "Got unexpected rectangle {%f, %f, %f, %f}.\n", destination_rects[0].left, destination_rects[0].top, destination_rects[0].right, destination_rects[0].bottom); - todo_wine ok(compare_rect_f(&destination_rects[1], 0, 0, 4, 4, 0), + ok(compare_rect_f(&destination_rects[1], 0, 0, 4, 4, 0), "Got unexpected rectangle {%f, %f, %f, %f}.\n", destination_rects[1].left, destination_rects[1].top, destination_rects[1].right, destination_rects[1].bottom); - todo_wine ok(compare_rect_f(&destination_rects[2], 0, 0, 4, 4, 0), + ok(compare_rect_f(&destination_rects[2], 0, 0, 4, 4, 0), "Got unexpected rectangle {%f, %f, %f, %f}.\n", destination_rects[2].left, destination_rects[2].top, destination_rects[2].right, destination_rects[2].bottom); - todo_wine ok(compare_rect_f(&destination_rects[3], 5, 5, 9, 9, 0), + ok(compare_rect_f(&destination_rects[3], 5, 5, 9, 9, 0), "Got unexpected rectangle {%f, %f, %f, %f}.\n", destination_rects[3].left, destination_rects[3].top, destination_rects[3].right, destination_rects[3].bottom); hr = ID2D1SpriteBatch_SetSprites(sprite_batch, 0, 0, NULL, NULL, NULL, NULL, 0, 0, 0, 0); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); hr = ID2D1SpriteBatch_SetSprites(sprite_batch, 0, 8, NULL, NULL, NULL, NULL, 0, 0, 0, 0); - todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#lx\n", hr); + ok(hr == E_INVALIDARG, "Got unexpected hr %#lx\n", hr); hr = ID2D1SpriteBatch_SetSprites(sprite_batch, 5, 1, NULL, NULL, NULL, NULL, 0, 0, 0, 0); - todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#lx\n", hr); + ok(hr == E_INVALIDARG, "Got unexpected hr %#lx\n", hr); hr = ID2D1SpriteBatch_SetSprites(sprite_batch, 0, 1, NULL, NULL, NULL, NULL, 0, 0, 0, 0); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); hr = ID2D1SpriteBatch_SetSprites(sprite_batch, 0, 8, &test_destination_rect[1], NULL, NULL, NULL, 0, 0, 0, 0); - todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#lx\n", hr); + ok(hr == E_INVALIDARG, "Got unexpected hr %#lx\n", hr); hr = ID2D1SpriteBatch_SetSprites(sprite_batch, 0, 1, &test_destination_rect[1], NULL, NULL, NULL, 0, 0, 0, 0); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 1, destination_rects, NULL, NULL, NULL); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); - todo_wine ok(compare_rect_f(&destination_rects[0], 5, 5, 9, 9, 0), + ok(compare_rect_f(&destination_rects[0], 5, 5, 9, 9, 0), "Got unexpected rectangle {%f, %f, %f, %f}.\n", destination_rects[0].left, destination_rects[0].top, destination_rects[0].right, destination_rects[0].bottom); @@ -18153,20 +18153,20 @@ static void test_sprite_batches(BOOL d3d11) { hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, test_destination_rect, NULL, NULL, NULL, sizeof(test_destination_rect->top), 0, 0, 0); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); - todo_wine ok(sprite_count == 2, "Expected sprite count of 2 got %d\n", sprite_count); + ok(sprite_count == 2, "Expected sprite count of 2 got %d\n", sprite_count); hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 2, destination_rects, source_rects, colors, transforms); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); - todo_wine ok(compare_rect_f(&destination_rects[0], 0, 0, 4, 4, 0), + ok(compare_rect_f(&destination_rects[0], 0, 0, 4, 4, 0), "Got unexpected rectangle {%f, %f, %f, %f}.\n", destination_rects[0].left, destination_rects[0].top, destination_rects[0].right, destination_rects[0].bottom); - todo_wine ok(compare_rect_f(&destination_rects[1], 0, 4, 4, 5, 0), + ok(compare_rect_f(&destination_rects[1], 0, 4, 4, 5, 0), "Got unexpected rectangle {%f, %f, %f, %f}.\n", destination_rects[1].left, destination_rects[1].top, destination_rects[1].right, destination_rects[1].bottom); @@ -18177,42 +18177,42 @@ static void test_sprite_batches(BOOL d3d11) { hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, test_destination_rect, NULL, NULL, NULL, sizeof(*test_destination_rect), 0, 0, 0); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); - todo_wine ok(sprite_count == 2, "Expected sprite count of 2 got %d\n", sprite_count); + ok(sprite_count == 2, "Expected sprite count of 2 got %d\n", sprite_count); hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 4, destination_rects, source_rects, colors, transforms); - todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#lx\n", hr); + ok(hr == E_INVALIDARG, "Got unexpected hr %#lx\n", hr); hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 3, 1, destination_rects, source_rects, colors, transforms); - todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#lx\n", hr); + ok(hr == E_INVALIDARG, "Got unexpected hr %#lx\n", hr); hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 3, 0, destination_rects, source_rects, colors, transforms); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 0, destination_rects, source_rects, colors, transforms); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 2, NULL, NULL, NULL, NULL); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 2, destination_rects, source_rects, colors, transforms); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 2, NULL, source_rects, NULL, NULL); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 2, destination_rects, NULL, NULL, NULL); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); - todo_wine ok(compare_rect_f(&destination_rects[0], 0, 0, 4, 4, 0), + ok(compare_rect_f(&destination_rects[0], 0, 0, 4, 4, 0), "Got unexpected rectangle {%f, %f, %f, %f}.\n", destination_rects[0].left, destination_rects[0].top, destination_rects[0].right, destination_rects[0].bottom); - todo_wine ok(compare_rect_f(&destination_rects[1], 5, 5, 9, 9, 0), + ok(compare_rect_f(&destination_rects[1], 5, 5, 9, 9, 0), "Got unexpected rectangle {%f, %f, %f, %f}.\n", destination_rects[1].left, destination_rects[1].top, destination_rects[1].right, destination_rects[1].bottom); @@ -18227,31 +18227,31 @@ static void test_sprite_batches(BOOL d3d11) { hr = ID2D1DeviceContext3_EndDraw(device, 0, 0); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); check = compare_surface(&ctx, "5e8144c13d1a71f0b59d54eba7156218693fa7bd"); - todo_wine ok(check, "Surface does not match.\n"); + ok(check, "Surface does not match.\n"); ID2D1DeviceContext3_BeginDraw(device); ID2D1DeviceContext3_DrawSpriteBatch(device, sprite_batch, 0, 2, bitmap, 0, D2D1_SPRITE_OPTIONS_NONE); hr = ID2D1DeviceContext3_EndDraw(device, 0, 0); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); check = compare_surface(&ctx, "064e9e8b46799904cab52b14d69a235d4f41409b"); - todo_wine ok(check, "Surface does not match.\n"); + ok(check, "Surface does not match.\n"); ID2D1SpriteBatch_Clear(sprite_batch); sprite_count = ID2D1SpriteBatch_GetSpriteCount(sprite_batch); ok(sprite_count == 0, "Expected sprite count of 0 got %d\n", sprite_count); hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, test_destination_rect, test_source_rect, NULL, NULL, sizeof(*test_destination_rect), sizeof(*test_source_rect), 0, 0); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); hr = ID2D1SpriteBatch_GetSprites(sprite_batch, 0, 2, destination_rects, source_rects, NULL, NULL); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); - todo_wine ok(compare_rect_f(&destination_rects[0], 0, 0, 4, 4, 0), + ok(compare_rect_f(&destination_rects[0], 0, 0, 4, 4, 0), "Got unexpected rectangle {%f, %f, %f, %f}.\n", destination_rects[0].left, destination_rects[0].top, destination_rects[0].right, destination_rects[0].bottom); - todo_wine ok(compare_rect_f(&destination_rects[1], 5, 5, 9, 9, 0), + ok(compare_rect_f(&destination_rects[1], 5, 5, 9, 9, 0), "Got unexpected rectangle {%f, %f, %f, %f}.\n", destination_rects[1].left, destination_rects[1].top, destination_rects[1].right, destination_rects[1].bottom); @@ -18281,7 +18281,7 @@ static void test_sprite_batches(BOOL d3d11) { set_matrix_identity(&test_matrixes[1]); scale_matrix(&test_matrixes[1], 4.0f, 4.0f); hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, test_destination_rect, test_source_rect, NULL, test_matrixes, sizeof(*test_destination_rect), sizeof(*test_source_rect), 0, sizeof(D2D1_MATRIX_3X2_F)); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); ID2D1DeviceContext3_BeginDraw(device); ID2D1DeviceContext3_DrawSpriteBatch(device, sprite_batch, 0, 2, bitmap, 0, D2D1_SPRITE_OPTIONS_NONE); @@ -18296,7 +18296,7 @@ static void test_sprite_batches(BOOL d3d11) { ok(sprite_count == 0, "Expected sprite count of 0 got %d\n", sprite_count); hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, test_destination_rect, test_source_rect, test_colors, NULL, sizeof(*test_destination_rect), sizeof(*test_source_rect), sizeof(D2D1_COLOR_F), 0); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); ID2D1DeviceContext3_BeginDraw(device); ID2D1DeviceContext3_DrawSpriteBatch(device, sprite_batch, 0, 2, bitmap, 0, D2D1_SPRITE_OPTIONS_NONE); @@ -18313,7 +18313,7 @@ static void test_sprite_batches(BOOL d3d11) { set_matrix_identity(&test_matrixes[1]); skew_matrix(&test_matrixes[1], 0.5f, 0.5f); hr = ID2D1SpriteBatch_AddSprites(sprite_batch, 2, test_destination_rect, test_source_rect, NULL, test_matrixes, sizeof(*test_destination_rect), sizeof(*test_source_rect), 0, sizeof(D2D1_MATRIX_3X2_F)); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx\n", hr); ID2D1DeviceContext3_BeginDraw(device); ID2D1DeviceContext3_DrawSpriteBatch(device, sprite_batch, 0, 2, bitmap, 0, D2D1_SPRITE_OPTIONS_NONE); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11249
From: Santino Mazza <smazza@codeweavers.com> --- dlls/d2d1/d2d1_private.h | 1 + dlls/d2d1/device.c | 18 +++++++++++++++++- dlls/d2d1/sprite_batch.c | 20 ++++++++++++++------ dlls/d2d1/tests/d2d1.c | 6 +++--- 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index 54ae00c6ac6..2609bfdeff2 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -469,6 +469,7 @@ struct d2d_sprite_batch { UINT32 sprite_count; UINT32 sprites_allocated; D2D1_RECT_F *destination_rectangles; + D2D1_RECT_U *source_rectangles; }; HRESULT d2d_create_sprite_batch(struct d2d_device_context *ctx, ID2D1SpriteBatch **iface); diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index c0322870692..ac25a044526 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -3046,18 +3046,34 @@ static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSpriteBatch(ID2D1Devic return d2d_create_sprite_batch(ctx, sprite_batch); } +static inline void convert_rect_u_to_rect_f(const D2D1_RECT_U *rect_u, D2D1_RECT_F *rect_f) { + rect_f->bottom = (float)(rect_u->bottom); + rect_f->top = (float)(rect_u->top); + rect_f->right = (float)(rect_u->right); + rect_f->left = (float)(rect_u->left); +} + +static inline BOOL is_rect_f_empty(const D2D1_RECT_F *rect_f) { + return rect_f->bottom == 0 && + rect_f->left == 0 && + rect_f->right == 0 && + rect_f->top == 0; +} + static void STDMETHODCALLTYPE d2d_device_context_DrawSpriteBatch(ID2D1DeviceContext6 *iface, ID2D1SpriteBatch *sprite_batch, UINT32 start_index, UINT32 sprite_count, ID2D1Bitmap *bitmap, D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, D2D1_SPRITE_OPTIONS sprite_options) { + D2D1_RECT_F source_rect; struct d2d_sprite_batch *sprite_batch_impl = unsafe_impl_from_ID2D1SpriteBatch(sprite_batch); TRACE("iface %p, sprite_batch %p, start_index %u, sprite_count %u, bitmap %p, interpolation_mode %u," "sprite_options %u\n", iface, sprite_batch, start_index, sprite_count, bitmap, interpolation_mode, sprite_options); for (int i = start_index; i < start_index + sprite_count; ++i) { + convert_rect_u_to_rect_f(&sprite_batch_impl->source_rectangles[i], &source_rect); ID2D1DeviceContext6_DrawBitmap(iface, bitmap, &sprite_batch_impl->destination_rectangles[i], 1.0f, - (D2D1_INTERPOLATION_MODE)interpolation_mode, 0, 0); + (D2D1_INTERPOLATION_MODE)interpolation_mode, is_rect_f_empty(&source_rect) ? NULL : &source_rect, 0); } } diff --git a/dlls/d2d1/sprite_batch.c b/dlls/d2d1/sprite_batch.c index 667501ffb84..eb4fb4e27b0 100644 --- a/dlls/d2d1/sprite_batch.c +++ b/dlls/d2d1/sprite_batch.c @@ -65,6 +65,7 @@ static ULONG STDMETHODCALLTYPE d2d_sprite_batch_Release(ID2D1SpriteBatch *iface) if (!refcount) { ID2D1Factory_Release(batch->factory); free(batch->destination_rectangles); + free(batch->source_rectangles); free(batch); } @@ -93,9 +94,6 @@ static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_AddSprites(ID2D1SpriteBatch *i if (!destination_rectangles) return S_OK; - if (source_rectangles) - FIXME("Source rectangles not implemented.\n"); - if (colors) FIXME("Color mask not implemented\n"); @@ -106,10 +104,17 @@ static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_AddSprites(ID2D1SpriteBatch *i { batch->sprites_allocated = max(batch->sprites_allocated + sprite_count, batch->sprites_allocated * 2); batch->destination_rectangles = realloc(batch->destination_rectangles, sizeof(D2D1_RECT_F) * batch->sprites_allocated); + batch->source_rectangles = realloc(batch->source_rectangles, batch->sprites_allocated * sizeof(D2D1_RECT_U)); } for (int i = 0; i < sprite_count; ++i) + { batch->destination_rectangles[i + batch->sprite_count] = *(D2D1_RECT_F *)(((UCHAR*)destination_rectangles) + i * destination_rectangles_stride); + if (source_rectangles) + batch->source_rectangles[i + batch->sprite_count] = *(D2D1_RECT_U *)(((UCHAR*)source_rectangles) + i * source_rectangles_stride); + else + batch->source_rectangles[i + batch->sprite_count] = (D2D1_RECT_U){0}; + } batch->sprite_count += sprite_count; @@ -134,9 +139,6 @@ static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_SetSprites(ID2D1SpriteBatch *i if (colors) FIXME("Color mask not implemented\n"); - if (source_rectangles) - FIXME("Source rectangles not implemented\n"); - if (transforms) FIXME("Transform matrixes not implemented\n"); @@ -144,6 +146,8 @@ static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_SetSprites(ID2D1SpriteBatch *i { if (destination_rectangles) batch->destination_rectangles[i] = *(D2D1_RECT_F *)(((UCHAR*)destination_rectangles) + i * destination_rectangles_stride); + if (source_rectangles) + batch->source_rectangles[i] = *(D2D1_RECT_U *)(((UCHAR*)source_rectangles) + i * source_rectangles_stride); } return S_OK; @@ -165,6 +169,9 @@ static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_GetSprites(ID2D1SpriteBatch *i if (destination_rectangles) memcpy(destination_rectangles, &batch->destination_rectangles[start_index], sizeof(D2D1_RECT_F) * sprite_count); + if (source_rectangles) + memcpy(source_rectangles, &batch->source_rectangles[start_index], sizeof(D2D1_RECT_U) * sprite_count); + return S_OK; } @@ -205,6 +212,7 @@ HRESULT d2d_create_sprite_batch(struct d2d_device_context *ctx, ID2D1SpriteBatch sprite_batch->sprites_allocated = 1; sprite_batch->destination_rectangles = calloc(sprite_batch->sprites_allocated, sizeof(D2D1_RECT_F)); + sprite_batch->source_rectangles = calloc(sprite_batch->sprites_allocated, sizeof(D2D1_RECT_U)); ID2D1Factory_AddRef(ctx->factory); sprite_batch->factory = ctx->factory; diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 11d8c6966ca..b93d3666ba0 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -18256,12 +18256,12 @@ static void test_sprite_batches(BOOL d3d11) { destination_rects[1].left, destination_rects[1].top, destination_rects[1].right, destination_rects[1].bottom); - todo_wine ok(compare_rect_u(&source_rects[0], 0, 0, 4, 4), + ok(compare_rect_u(&source_rects[0], 0, 0, 4, 4), "Got unexpected rectangle {%u, %u, %u, %u}.\n", source_rects[0].left, source_rects[0].top, source_rects[0].right, source_rects[0].bottom); - todo_wine ok(compare_rect_u(&source_rects[1], 1, 1, 4, 4), + ok(compare_rect_u(&source_rects[1], 1, 1, 4, 4), "Got unexpected rectangle {%u, %u, %u, %u}.\n", source_rects[1].left, source_rects[1].top, source_rects[1].right, source_rects[1].bottom); @@ -18271,7 +18271,7 @@ static void test_sprite_batches(BOOL d3d11) { hr = ID2D1DeviceContext3_EndDraw(device, 0, 0); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); check = compare_surface(&ctx, "9133aab139f4c0ec2edea7e3c63069370ff88083"); - todo_wine ok(check, "Surface does not match.\n"); + ok(check, "Surface does not match.\n"); ID2D1SpriteBatch_Clear(sprite_batch); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11249
From: Santino Mazza <smazza@codeweavers.com> --- dlls/d2d1/d2d1_private.h | 1 + dlls/d2d1/device.c | 3 +++ dlls/d2d1/sprite_batch.c | 29 +++++++++++++++++++++++------ dlls/d2d1/tests/d2d1.c | 4 ++-- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index 2609bfdeff2..a095aaef66c 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -470,6 +470,7 @@ struct d2d_sprite_batch { UINT32 sprites_allocated; D2D1_RECT_F *destination_rectangles; D2D1_RECT_U *source_rectangles; + D2D1_MATRIX_3X2_F *transform_matrixes; }; HRESULT d2d_create_sprite_batch(struct d2d_device_context *ctx, ID2D1SpriteBatch **iface); diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index ac25a044526..5ad1b32421a 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -3072,9 +3072,12 @@ static void STDMETHODCALLTYPE d2d_device_context_DrawSpriteBatch(ID2D1DeviceCont for (int i = start_index; i < start_index + sprite_count; ++i) { convert_rect_u_to_rect_f(&sprite_batch_impl->source_rectangles[i], &source_rect); + ID2D1DeviceContext6_SetTransform(iface, &sprite_batch_impl->transform_matrixes[i]); ID2D1DeviceContext6_DrawBitmap(iface, bitmap, &sprite_batch_impl->destination_rectangles[i], 1.0f, (D2D1_INTERPOLATION_MODE)interpolation_mode, is_rect_f_empty(&source_rect) ? NULL : &source_rect, 0); } + + ID2D1DeviceContext6_SetTransform(iface, &identity); } static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSvgGlyphStyle(ID2D1DeviceContext6 *iface, diff --git a/dlls/d2d1/sprite_batch.c b/dlls/d2d1/sprite_batch.c index eb4fb4e27b0..edc43b43585 100644 --- a/dlls/d2d1/sprite_batch.c +++ b/dlls/d2d1/sprite_batch.c @@ -66,6 +66,7 @@ static ULONG STDMETHODCALLTYPE d2d_sprite_batch_Release(ID2D1SpriteBatch *iface) ID2D1Factory_Release(batch->factory); free(batch->destination_rectangles); free(batch->source_rectangles); + free(batch->transform_matrixes); free(batch); } @@ -82,6 +83,16 @@ static void STDMETHODCALLTYPE d2d_sprite_batch_GetFactory(ID2D1SpriteBatch *ifac ID2D1Factory_AddRef(*factory); } +static void set_matrix_identity(D2D1_MATRIX_3X2_F *matrix) +{ + matrix->_11 = 1.0f; + matrix->_12 = 0.0f; + matrix->_21 = 0.0f; + matrix->_22 = 1.0f; + matrix->_31 = 0.0f; + matrix->_32 = 0.0f; +} + static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_AddSprites(ID2D1SpriteBatch *iface, UINT32 sprite_count, const D2D1_RECT_F *destination_rectangles, const D2D1_RECT_U *source_rectangles, const D2D1_COLOR_F *colors, const D2D1_MATRIX_3X2_F *transforms, UINT32 destination_rectangles_stride, UINT32 source_rectangles_stride, @@ -97,14 +108,12 @@ static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_AddSprites(ID2D1SpriteBatch *i if (colors) FIXME("Color mask not implemented\n"); - if (transforms) - FIXME("Transform matrixes not implemented.\n"); - if (batch->sprites_allocated <= batch->sprite_count + sprite_count) { batch->sprites_allocated = max(batch->sprites_allocated + sprite_count, batch->sprites_allocated * 2); batch->destination_rectangles = realloc(batch->destination_rectangles, sizeof(D2D1_RECT_F) * batch->sprites_allocated); batch->source_rectangles = realloc(batch->source_rectangles, batch->sprites_allocated * sizeof(D2D1_RECT_U)); + batch->transform_matrixes = realloc(batch->transform_matrixes, batch->sprites_allocated * sizeof(D2D1_MATRIX_3X2_F)); } for (int i = 0; i < sprite_count; ++i) @@ -114,6 +123,11 @@ static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_AddSprites(ID2D1SpriteBatch *i batch->source_rectangles[i + batch->sprite_count] = *(D2D1_RECT_U *)(((UCHAR*)source_rectangles) + i * source_rectangles_stride); else batch->source_rectangles[i + batch->sprite_count] = (D2D1_RECT_U){0}; + + if (transforms) + batch->transform_matrixes[i + batch->sprite_count] = *(D2D1_MATRIX_3X2_F *)(((UCHAR*)transforms) + i * transforms_stride); + else + set_matrix_identity(&batch->transform_matrixes[i + batch->sprite_count]); } batch->sprite_count += sprite_count; @@ -139,15 +153,14 @@ static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_SetSprites(ID2D1SpriteBatch *i if (colors) FIXME("Color mask not implemented\n"); - if (transforms) - FIXME("Transform matrixes not implemented\n"); - for (int i = start_index; i < start_index + sprite_count; ++i) { if (destination_rectangles) batch->destination_rectangles[i] = *(D2D1_RECT_F *)(((UCHAR*)destination_rectangles) + i * destination_rectangles_stride); if (source_rectangles) batch->source_rectangles[i] = *(D2D1_RECT_U *)(((UCHAR*)source_rectangles) + i * source_rectangles_stride); + if (transforms) + batch->transform_matrixes[i] = *(D2D1_MATRIX_3X2_F *)(((UCHAR*)transforms) + i * transforms_stride); } return S_OK; @@ -172,6 +185,9 @@ static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_GetSprites(ID2D1SpriteBatch *i if (source_rectangles) memcpy(source_rectangles, &batch->source_rectangles[start_index], sizeof(D2D1_RECT_U) * sprite_count); + if (transforms) + memcpy(transforms, &batch->transform_matrixes[start_index], sizeof(D2D1_MATRIX_3X2_F) * sprite_count); + return S_OK; } @@ -213,6 +229,7 @@ HRESULT d2d_create_sprite_batch(struct d2d_device_context *ctx, ID2D1SpriteBatch sprite_batch->sprites_allocated = 1; sprite_batch->destination_rectangles = calloc(sprite_batch->sprites_allocated, sizeof(D2D1_RECT_F)); sprite_batch->source_rectangles = calloc(sprite_batch->sprites_allocated, sizeof(D2D1_RECT_U)); + sprite_batch->transform_matrixes = calloc(sprite_batch->sprites_allocated, sizeof(D2D1_MATRIX_3X2_F)); ID2D1Factory_AddRef(ctx->factory); sprite_batch->factory = ctx->factory; diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index b93d3666ba0..b51f3ca437f 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -18288,7 +18288,7 @@ static void test_sprite_batches(BOOL d3d11) { hr = ID2D1DeviceContext3_EndDraw(device, 0, 0); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); check = compare_surface(&ctx, "30bf2de6f4f10ae8ebfc61261ad0d0a4abfed094"); - todo_wine ok(check, "Surface does not match.\n"); + ok(check, "Surface does not match.\n"); ID2D1SpriteBatch_Clear(sprite_batch); @@ -18320,7 +18320,7 @@ static void test_sprite_batches(BOOL d3d11) { hr = ID2D1DeviceContext3_EndDraw(device, 0, 0); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); check = compare_surface(&ctx, "72d4c7723073eabc2d7d1939b6f41040546b21f7"); - todo_wine ok(check, "Surface does not match.\n"); + todo_wine ok(check, "Surface does not match.\n"); // FIXME: Anti Aliasing issue? If instead of skewing I just translate or scale the surface matches. ID2D1DeviceContext3_SetAntialiasMode(device, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11249
Nikolay Sivov (@nsivov) commented about dlls/d2d1/d2d1_private.h:
unsigned int d2d_get_bitmap_options_for_surface(IDXGISurface *surface); struct d2d_bitmap *unsafe_impl_from_ID2D1Bitmap(ID2D1Bitmap *iface);
+struct d2d_sprite_batch { + ID2D1SpriteBatch ID2D1SpriteBatch_iface; + + LONG refcount; +}; + +HRESULT d2d_create_sprite_batch(struct d2d_device_context *ctx, ID2D1SpriteBatch **iface); + Please use formatting and arguments to the object creation function same as in existing functions.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11249#note_144093
Nikolay Sivov (@nsivov) commented about dlls/d2d1/sprite_batch.c:
+static inline struct d2d_sprite_batch *impl_from_ID2D1SpriteBatch(ID2D1SpriteBatch *iface) +{ + return CONTAINING_RECORD(iface, struct d2d_sprite_batch, ID2D1SpriteBatch_iface); +} + +static HRESULT STDMETHODCALLTYPE d2d_sprite_batch_QueryInterface(ID2D1SpriteBatch *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_ID2D1SpriteBatch) + || IsEqualGUID(iid, &IID_IUnknown)) + { + ID2D1SpriteBatch_AddRef(iface); + *out = iface; + return S_OK; + } This is incomplete.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11249#note_144095
Nikolay Sivov (@nsivov) commented about dlls/d2d1/device.c:
static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSpriteBatch(ID2D1DeviceContext6 *iface, ID2D1SpriteBatch **sprite_batch) { - FIXME("iface %p, sprite_batch %p stub!\n", iface, sprite_batch); + struct d2d_device_context *ctx = impl_from_ID2D1DeviceContext(iface); It's called 'context' in other functions.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11249#note_144094
Nikolay Sivov (@nsivov) commented about dlls/d2d1/sprite_batch.c:
+ d2d_sprite_batch_GetSprites, + d2d_sprite_batch_GetSpritesCount, + d2d_sprite_batch_Clear +}; + +HRESULT d2d_create_sprite_batch(struct d2d_device_context *ctx, ID2D1SpriteBatch **iface) { + struct d2d_sprite_batch *sprite_batch; + + if (!(sprite_batch = calloc(1, sizeof(*sprite_batch)))) + return E_OUTOFMEMORY; + + sprite_batch->ID2D1SpriteBatch_iface.lpVtbl = &d2d_sprite_batch_vtbl; + + ID2D1SpriteBatch_AddRef(&sprite_batch->ID2D1SpriteBatch_iface); + *iface = &sprite_batch->ID2D1SpriteBatch_iface; + Again, follow what existing functions are doing. There is no need for AddRef.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11249#note_144096
Nikolay Sivov (@nsivov) commented about dlls/d2d1/tests/d2d1.c:
&& compare_float(point->y, y, ulps); }
-static BOOL compare_rect(const D2D1_RECT_F *rect, float left, float top, float right, float bottom, unsigned int ulps) +static BOOL compare_rect_f(const D2D1_RECT_F *rect, float left, float top, float right, float bottom, unsigned int ulps) {
Could you simply introduce new function, without renaming this one? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11249#note_144097
Nikolay Sivov (@nsivov) commented about dlls/d2d1/sprite_batch.c:
+ + if (source_rectangles) + FIXME("Source rectangles not implemented.\n"); + + if (colors) + FIXME("Color mask not implemented\n"); + + if (transforms) + FIXME("Transform matrixes not implemented.\n"); + + if (batch->sprites_allocated <= batch->sprite_count + sprite_count) + { + batch->sprites_allocated = max(batch->sprites_allocated + sprite_count, batch->sprites_allocated * 2); + batch->destination_rectangles = realloc(batch->destination_rectangles, sizeof(D2D1_RECT_F) * batch->sprites_allocated); + } + Let's use array_reserve function for this one.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11249#note_144098
Nikolay Sivov (@nsivov) commented about dlls/d2d1/sprite_batch.c:
+ if (colors) + FIXME("Color mask not implemented\n");
- return E_NOTIMPL; + if (source_rectangles) + FIXME("Source rectangles not implemented\n"); + + if (transforms) + FIXME("Transform matrixes not implemented\n"); + + for (int i = start_index; i < start_index + sprite_count; ++i) + { + if (destination_rectangles) + batch->destination_rectangles[i] = *(D2D1_RECT_F *)(((UCHAR*)destination_rectangles) + i * destination_rectangles_stride); + } + Why enter a loop if there is no rectangles to copy?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11249#note_144099
Nikolay Sivov (@nsivov) commented about dlls/d2d1/sprite_batch.c:
sprite_batch->sprites_allocated = 1; sprite_batch->destination_rectangles = calloc(sprite_batch->sprites_allocated, sizeof(D2D1_RECT_F)); sprite_batch->source_rectangles = calloc(sprite_batch->sprites_allocated, sizeof(D2D1_RECT_U)); + sprite_batch->transform_matrixes = calloc(sprite_batch->sprites_allocated, sizeof(D2D1_MATRIX_3X2_F));
Can you have source rectangles/matrices specified only for some of the sprites? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11249#note_144101
Nikolay Sivov (@nsivov) commented about dlls/d2d1/sprite_batch.c:
sprite_batch->ID2D1SpriteBatch_iface.lpVtbl = &d2d_sprite_batch_vtbl;
+ sprite_batch->sprites_allocated = 1; + sprite_batch->destination_rectangles = calloc(sprite_batch->sprites_allocated, sizeof(D2D1_RECT_F));
This doesn't look necessary. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11249#note_144100
Nikolay Sivov (@nsivov) commented about dlls/d2d1/device.c:
ID2D1SpriteBatch *sprite_batch, UINT32 start_index, UINT32 sprite_count, ID2D1Bitmap *bitmap, D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, D2D1_SPRITE_OPTIONS sprite_options) { - FIXME("iface %p, sprite_batch %p, start_index %u, sprite_count %u, bitmap %p, interpolation_mode %u," - "sprite_options %u stub!\n", iface, sprite_batch, start_index, sprite_count, bitmap, + struct d2d_sprite_batch *sprite_batch_impl = unsafe_impl_from_ID2D1SpriteBatch(sprite_batch); + TRACE("iface %p, sprite_batch %p, start_index %u, sprite_count %u, bitmap %p, interpolation_mode %u," + "sprite_options %u\n", iface, sprite_batch, start_index, sprite_count, bitmap, interpolation_mode, sprite_options); + + for (int i = start_index; i < start_index + sprite_count; ++i) { + ID2D1DeviceContext6_DrawBitmap(iface, bitmap, &sprite_batch_impl->destination_rectangles[i], 1.0f, + (D2D1_INTERPOLATION_MODE)interpolation_mode, 0, 0); + } }
This is most likely incorrect for command list case, since it has dedicated method for sprites. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11249#note_144102
A commit with a stub and tests should be split, and you could skip stub part, since you change it right away. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11249#note_144103
On Wed Jun 24 13:41:44 2026 +0000, Nikolay Sivov wrote:
Can you have source rectangles/matrices specified only for some of the sprites? Yes, if no matrix is specified the identity one is used, for source rectangles it uses the size of the whole bitmap if none is specified.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11249#note_144163
participants (3)
-
Nikolay Sivov (@nsivov) -
Santino Mazza -
Santino Mazza (@tati)