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