[PATCH v3 0/6] MR11674: d3dx10: Some fixes and tests for sprites.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> -- v3: d3dx10/tests: Add some sprites rendering tests. https://gitlab.winehq.org/wine/wine/-/merge_requests/11674
From: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> --- dlls/d3dx10_43/sprite.c | 35 +++++++++++++++++++++++++++++++++-- dlls/d3dx10_43/tests/d3dx10.c | 14 +++----------- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/dlls/d3dx10_43/sprite.c b/dlls/d3dx10_43/sprite.c index 6feae868a44..9065e1e647f 100644 --- a/dlls/d3dx10_43/sprite.c +++ b/dlls/d3dx10_43/sprite.c @@ -25,6 +25,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3dx); #define D3DERR_INVALIDCALL 0x8876086c +#define D3DX10_SPRITE_READY 0x10000000 struct d3dx10_sprite { @@ -33,6 +34,7 @@ struct d3dx10_sprite D3DXMATRIX projection; ID3D10Device *device; + unsigned int flags; }; static inline struct d3dx10_sprite *impl_from_ID3DX10Sprite(ID3DX10Sprite *iface) @@ -86,40 +88,69 @@ static ULONG WINAPI d3dx10_sprite_Release(ID3DX10Sprite *iface) static HRESULT WINAPI d3dx10_sprite_Begin(ID3DX10Sprite *iface, UINT flags) { + struct d3dx10_sprite *sprite = impl_from_ID3DX10Sprite(iface); + FIXME("iface %p, flags %#x stub!\n", iface, flags); - return E_NOTIMPL; + if (sprite->flags & D3DX10_SPRITE_READY) + return E_FAIL; + + sprite->flags = flags | D3DX10_SPRITE_READY; + + return S_OK; } static HRESULT WINAPI d3dx10_sprite_DrawSpritesBuffered(ID3DX10Sprite *iface, D3DX10_SPRITE *sprites, UINT count) { + struct d3dx10_sprite *sprite = impl_from_ID3DX10Sprite(iface); + FIXME("iface %p, sprites %p, count %u stub!\n", iface, sprites, count); + if (!(sprite->flags & D3DX10_SPRITE_READY)) + return E_FAIL; + return E_NOTIMPL; } static HRESULT WINAPI d3dx10_sprite_Flush(ID3DX10Sprite *iface) { + struct d3dx10_sprite *sprite = impl_from_ID3DX10Sprite(iface); + FIXME("iface %p stub!\n", iface); + if (!(sprite->flags & D3DX10_SPRITE_READY)) + return E_FAIL; + return E_NOTIMPL; } static HRESULT WINAPI d3dx10_sprite_DrawSpritesImmediate(ID3DX10Sprite *iface, D3DX10_SPRITE *sprites, UINT count, UINT size, UINT flags) { + struct d3dx10_sprite *sprite = impl_from_ID3DX10Sprite(iface); + FIXME("iface %p, sprites %p, count %u, size %u, flags %#x stub!\n", iface, sprites, count, size, flags); + if (!(sprite->flags & D3DX10_SPRITE_READY)) + return E_FAIL; + return E_NOTIMPL; } static HRESULT WINAPI d3dx10_sprite_End(ID3DX10Sprite *iface) { + struct d3dx10_sprite *sprite = impl_from_ID3DX10Sprite(iface); + FIXME("iface %p stub!\n", iface); - return E_NOTIMPL; + if (!(sprite->flags & D3DX10_SPRITE_READY)) + return E_FAIL; + + sprite->flags = 0; + + return S_OK; } static HRESULT WINAPI d3dx10_sprite_GetViewTransform(ID3DX10Sprite *iface, D3DXMATRIX *transform) diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 0008a995ff8..f194f7d378d 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -7734,42 +7734,37 @@ static void test_sprite(void) /* Begin */ hr = ID3DX10Sprite_Begin(sprite, 0); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = ID3DX10Sprite_Begin(sprite, 0); + ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr); + /* Flush/End */ hr = ID3DX10Sprite_Flush(sprite); todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = ID3DX10Sprite_End(sprite); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); /* May not be called before next Begin */ hr = ID3DX10Sprite_Flush(sprite); - todo_wine ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr); hr = ID3DX10Sprite_End(sprite); - todo_wine ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr); /* Draw */ hr = ID3DX10Sprite_DrawSpritesBuffered(sprite, NULL, 0); - todo_wine ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr); memset(&sprite_desc, 0, sizeof(sprite_desc)); hr = ID3DX10Sprite_DrawSpritesBuffered(sprite, &sprite_desc, 0); - todo_wine ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr); hr = ID3DX10Sprite_DrawSpritesBuffered(sprite, &sprite_desc, 1); - todo_wine ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr); hr = ID3DX10Sprite_Begin(sprite, 0); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); memset(&sprite_desc, 0, sizeof(sprite_desc)); @@ -7791,12 +7786,10 @@ static void test_sprite(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = ID3DX10Sprite_End(sprite); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); /* D3DX10_SPRITE_ADDREF_TEXTURES */ hr = ID3DX10Sprite_Begin(sprite, D3DX10_SPRITE_ADDREF_TEXTURES); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); memset(&sprite_desc, 0, sizeof(sprite_desc)); @@ -7815,7 +7808,6 @@ todo_wine { ok(get_refcount(srv1) == refcount, "Unexpected refcount.\n"); hr = ID3DX10Sprite_End(sprite); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ID3DX10Sprite_Release(sprite); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11674
From: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> --- dlls/d3dx10_43/tests/d3dx10.c | 81 ++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index f194f7d378d..645ce527ee1 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -3238,12 +3238,6 @@ static void check_test_resource_data_(unsigned int line, ID3D10Resource *resourc } } -static void test_D3DX10UnsetAllDeviceObjects(void) -{ - static const D3D10_INPUT_ELEMENT_DESC layout_desc[] = - { - {"POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0}, - }; #if 0 float4 main(float4 pos : POSITION) : POSITION { @@ -3261,6 +3255,13 @@ float4 main(float4 pos : POSITION) : POSITION 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, }; +static void test_D3DX10UnsetAllDeviceObjects(void) +{ + static const D3D10_INPUT_ELEMENT_DESC layout_desc[] = + { + {"POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0}, + }; + #if 0 struct gs_out { @@ -7815,7 +7816,74 @@ todo_wine { ID3D10Texture2D_Release(texture2); ID3D10ShaderResourceView_Release(srv1); ID3D10ShaderResourceView_Release(srv2); + refcount = ID3D10Device_Release(device); + ok(!refcount, "Unexpected refcount.\n"); +} + +static void test_sprite_save_state(void) +{ + ID3D10VertexShader *vs, *vs2, *tmp_vs; + D3D10_PRIMITIVE_TOPOLOGY topology; + ID3DX10Sprite *sprite; + float blend_factor[4]; + ID3D10Device *device; + ULONG refcount; + HRESULT hr; + + if (!(device = create_device())) + { + skip("Failed to create device, skipping tests.\n"); + return; + } + hr = ID3D10Device_CreateVertexShader(device, simple_vs, sizeof(simple_vs), &vs); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = ID3D10Device_CreateVertexShader(device, simple_vs, sizeof(simple_vs), &vs2); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = D3DX10CreateSprite(device, 0, &sprite); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + /* State restore behavior. */ + blend_factor[0] = 0.1f; + blend_factor[1] = 0.2f; + blend_factor[2] = 0.3f; + blend_factor[3] = 0.4f; + ID3D10Device_OMSetBlendState(device, NULL, blend_factor, 0); + ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_POINTLIST); + ID3D10Device_VSSetShader(device, vs); + + hr = ID3DX10Sprite_Begin(sprite, D3DX10_SPRITE_SAVE_STATE); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + blend_factor[0] = 0.5f; + blend_factor[1] = 0.6f; + blend_factor[2] = 0.7f; + blend_factor[3] = 0.8f; + ID3D10Device_OMSetBlendState(device, NULL, blend_factor, 0); + ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_LINELIST); + ID3D10Device_VSSetShader(device, vs2); + + hr = ID3DX10Sprite_End(sprite); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + ID3D10Device_OMGetBlendState(device, NULL, blend_factor, NULL); + ok(blend_factor[0] == 0.5f && blend_factor[1] == 0.6f + && blend_factor[2] == 0.7f && blend_factor[3] == 0.8f, + "Got unexpected blend factor {%.8e, %.8e, %.8e, %.8e}.\n", + blend_factor[0], blend_factor[1], blend_factor[2], blend_factor[3]); + ID3D10Device_IAGetPrimitiveTopology(device, &topology); + todo_wine + ok(topology == D3D10_PRIMITIVE_TOPOLOGY_POINTLIST, "Unexpected topology %d.\n", topology); + ID3D10Device_VSGetShader(device, &tmp_vs); + todo_wine + ok(vs == tmp_vs, "Unexpected shader.\n"); + ID3D10VertexShader_Release(tmp_vs); + + ID3DX10Sprite_Release(sprite); + + ID3D10VertexShader_Release(vs2); + ID3D10VertexShader_Release(vs); refcount = ID3D10Device_Release(device); ok(!refcount, "Unexpected refcount.\n"); } @@ -8173,6 +8241,7 @@ START_TEST(d3dx10) test_create_texture(); test_font(); test_sprite(); + test_sprite_save_state(); test_create_effect_from_memory(); test_create_effect_from_file(); test_create_effect_from_resource(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11674
From: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> --- dlls/d3dx10_43/sprite.c | 17 +++++++++++++++++ dlls/d3dx10_43/tests/d3dx10.c | 3 +-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/dlls/d3dx10_43/sprite.c b/dlls/d3dx10_43/sprite.c index 9065e1e647f..8607cb124a5 100644 --- a/dlls/d3dx10_43/sprite.c +++ b/dlls/d3dx10_43/sprite.c @@ -34,6 +34,7 @@ struct d3dx10_sprite D3DXMATRIX projection; ID3D10Device *device; + ID3D10StateBlock *state_block; unsigned int flags; }; @@ -80,6 +81,8 @@ static ULONG WINAPI d3dx10_sprite_Release(ID3DX10Sprite *iface) if (!refcount) { ID3D10Device_Release(sprite->device); + if (sprite->state_block) + IUnknown_Release(sprite->state_block); free(sprite); } @@ -96,6 +99,8 @@ static HRESULT WINAPI d3dx10_sprite_Begin(ID3DX10Sprite *iface, UINT flags) return E_FAIL; sprite->flags = flags | D3DX10_SPRITE_READY; + if (sprite->flags & D3DX10_SPRITE_SAVE_STATE) + sprite->state_block->lpVtbl->Capture(sprite->state_block); return S_OK; } @@ -148,6 +153,8 @@ static HRESULT WINAPI d3dx10_sprite_End(ID3DX10Sprite *iface) if (!(sprite->flags & D3DX10_SPRITE_READY)) return E_FAIL; + if (sprite->flags & D3DX10_SPRITE_SAVE_STATE) + sprite->state_block->lpVtbl->Apply(sprite->state_block); sprite->flags = 0; return S_OK; @@ -231,6 +238,8 @@ static const ID3DX10SpriteVtbl d3dx10_sprite_vtbl = HRESULT WINAPI D3DX10CreateSprite(ID3D10Device *device, UINT size, ID3DX10Sprite **sprite) { struct d3dx10_sprite *object; + D3D10_STATE_BLOCK_MASK mask; + HRESULT hr; TRACE("device %p, size %u, sprite %p.\n", device, size, sprite); @@ -251,6 +260,14 @@ HRESULT WINAPI D3DX10CreateSprite(ID3D10Device *device, UINT size, ID3DX10Sprite object->projection._33 = 1.0f; object->projection._44 = 1.0f; + /* TODO: we shouldn't be capturing entire state */ + D3D10StateBlockMaskEnableAll(&mask); + if (FAILED(hr = D3D10CreateStateBlock(device, &mask, &object->state_block))) + { + ID3DX10Sprite_Release(&object->ID3DX10Sprite_iface); + return hr; + } + *sprite = &object->ID3DX10Sprite_iface; return S_OK; diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 645ce527ee1..721c2d6df51 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -7868,15 +7868,14 @@ static void test_sprite_save_state(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ID3D10Device_OMGetBlendState(device, NULL, blend_factor, NULL); + todo_wine ok(blend_factor[0] == 0.5f && blend_factor[1] == 0.6f && blend_factor[2] == 0.7f && blend_factor[3] == 0.8f, "Got unexpected blend factor {%.8e, %.8e, %.8e, %.8e}.\n", blend_factor[0], blend_factor[1], blend_factor[2], blend_factor[3]); ID3D10Device_IAGetPrimitiveTopology(device, &topology); - todo_wine ok(topology == D3D10_PRIMITIVE_TOPOLOGY_POINTLIST, "Unexpected topology %d.\n", topology); ID3D10Device_VSGetShader(device, &tmp_vs); - todo_wine ok(vs == tmp_vs, "Unexpected shader.\n"); ID3D10VertexShader_Release(tmp_vs); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11674
From: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> --- dlls/d3dx10_43/sprite.c | 74 ++++++++++++++++++++++++++++++++++- dlls/d3dx10_43/tests/d3dx10.c | 3 +- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/dlls/d3dx10_43/sprite.c b/dlls/d3dx10_43/sprite.c index 8607cb124a5..b40c4793cca 100644 --- a/dlls/d3dx10_43/sprite.c +++ b/dlls/d3dx10_43/sprite.c @@ -19,6 +19,7 @@ #define COBJMACROS #include "d3dx10.h" +#include <stdbool.h> #include "wine/debug.h" @@ -32,12 +33,64 @@ struct d3dx10_sprite ID3DX10Sprite ID3DX10Sprite_iface; LONG refcount; + struct + { + D3DX10_SPRITE *sprites; + size_t count; + size_t capacity; + } buffer; D3DXMATRIX projection; ID3D10Device *device; ID3D10StateBlock *state_block; unsigned int flags; }; +static bool d3dx_array_reserve(void **elements, size_t *capacity, size_t count, size_t size) +{ + size_t new_capacity, max_capacity; + void *new_elements; + + if (count <= *capacity) + return true; + + max_capacity = ~(size_t)0 / size; + if (count > max_capacity) + return false; + + new_capacity = max(4, *capacity); + while (new_capacity < count && new_capacity <= max_capacity / 2) + new_capacity *= 2; + if (new_capacity < count) + new_capacity = max_capacity; + + if (!(new_elements = realloc(*elements, new_capacity * size))) + return false; + + *elements = new_elements; + *capacity = new_capacity; + return true; +} + +static void d3dx10_sprite_clear_batch(struct d3dx10_sprite *sprite) +{ + if (sprite->flags & D3DX10_SPRITE_ADDREF_TEXTURES) + { + for (size_t i = 0; i < sprite->buffer.count; ++i) + { + if (sprite->buffer.sprites[i].pTexture) + ID3D10ShaderResourceView_Release(sprite->buffer.sprites[i].pTexture); + } + } + + sprite->buffer.count = 0; +} + +static void d3dx10_sprite_flush(struct d3dx10_sprite *sprite) +{ + /* TODO: draw batched sprites */ + d3dx10_sprite_clear_batch(sprite); +} + static inline struct d3dx10_sprite *impl_from_ID3DX10Sprite(ID3DX10Sprite *iface) { return CONTAINING_RECORD(iface, struct d3dx10_sprite, ID3DX10Sprite_iface); @@ -83,6 +136,8 @@ static ULONG WINAPI d3dx10_sprite_Release(ID3DX10Sprite *iface) ID3D10Device_Release(sprite->device); if (sprite->state_block) IUnknown_Release(sprite->state_block); + d3dx10_sprite_clear_batch(sprite); + free(sprite->buffer.sprites); free(sprite); } @@ -110,11 +165,24 @@ static HRESULT WINAPI d3dx10_sprite_DrawSpritesBuffered(ID3DX10Sprite *iface, { struct d3dx10_sprite *sprite = impl_from_ID3DX10Sprite(iface); - FIXME("iface %p, sprites %p, count %u stub!\n", iface, sprites, count); + TRACE("iface %p, sprites %p, count %u.\n", iface, sprites, count); if (!(sprite->flags & D3DX10_SPRITE_READY)) return E_FAIL; + if (!d3dx_array_reserve((void **)&sprite->buffer.sprites, &sprite->buffer.capacity, + sprite->buffer.count + count, sizeof(*sprite->buffer.sprites))) + { + return E_OUTOFMEMORY; + } + + for (unsigned int i = 0; i < count; ++i) + { + sprite->buffer.sprites[sprite->buffer.count++] = sprites[i]; + if (sprite->flags & D3DX10_SPRITE_ADDREF_TEXTURES) + ID3D10ShaderResourceView_AddRef(sprites[i].pTexture); + } + return E_NOTIMPL; } @@ -127,6 +195,8 @@ static HRESULT WINAPI d3dx10_sprite_Flush(ID3DX10Sprite *iface) if (!(sprite->flags & D3DX10_SPRITE_READY)) return E_FAIL; + d3dx10_sprite_flush(sprite); + return E_NOTIMPL; } @@ -153,6 +223,8 @@ static HRESULT WINAPI d3dx10_sprite_End(ID3DX10Sprite *iface) if (!(sprite->flags & D3DX10_SPRITE_READY)) return E_FAIL; + d3dx10_sprite_flush(sprite); + if (sprite->flags & D3DX10_SPRITE_SAVE_STATE) sprite->state_block->lpVtbl->Apply(sprite->state_block); sprite->flags = 0; diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 721c2d6df51..fd5e8853daa 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -7798,10 +7798,9 @@ static void test_sprite(void) refcount = get_refcount(srv1); hr = ID3DX10Sprite_DrawSpritesBuffered(sprite, &sprite_desc, 1); -todo_wine { +todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(get_refcount(srv1) > refcount, "Unexpected refcount.\n"); -} hr = ID3DX10Sprite_Flush(sprite); todo_wine -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11674
From: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> --- include/d3dx10math.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/d3dx10math.h b/include/d3dx10math.h index 5790fbdf63b..89ec45812ae 100644 --- a/include/d3dx10math.h +++ b/include/d3dx10math.h @@ -256,6 +256,15 @@ D3DXCOLOR *D3DXColorModulate(D3DXCOLOR *out, D3DXCOLOR c1, D3DXCOLOR c2); D3DXCOLOR *D3DXColorScale(D3DXCOLOR *out, D3DXCOLOR c, float s); D3DXCOLOR *D3DXColorSubtract(D3DXCOLOR *out, D3DXCOLOR c1, D3DXCOLOR c2); D3DX_CPU_OPTIMIZATION WINAPI D3DXCpuOptimizations(BOOL enable); +D3DXMATRIX *WINAPI D3DXMatrixTranslation(D3DXMATRIX *m, float x, float y, float z); +D3DXMATRIX *WINAPI D3DXMatrixPerspectiveFovLH(D3DXMATRIX *m, float fovy, float aspect, float zn, float zf); +D3DXMATRIX *WINAPI D3DXMatrixTranslation(D3DXMATRIX *m, float x, float y, float z); +D3DXMATRIX *WINAPI D3DXMatrixRotationX(D3DXMATRIX *m, float angle); +D3DXMATRIX *WINAPI D3DXMatrixRotationY(D3DXMATRIX *m, float angle); +D3DXMATRIX *WINAPI D3DXMatrixRotationZ(D3DXMATRIX *m, float angle); +D3DXMATRIX *WINAPI D3DXMatrixPerspectiveLH(D3DXMATRIX *m, float w, float h, float zn, float zf); +D3DXVECTOR4 *WINAPI D3DXVec2TransformArray(D3DXVECTOR4 *pout, UINT outstride, const D3DXVECTOR2 *pv, + UINT vstride, const D3DXMATRIX *pm, UINT n); #ifdef __cplusplus } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11674
From: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> --- dlls/d3dx10_33/tests/Makefile.in | 2 +- dlls/d3dx10_34/tests/Makefile.in | 2 +- dlls/d3dx10_35/tests/Makefile.in | 2 +- dlls/d3dx10_36/tests/Makefile.in | 2 +- dlls/d3dx10_37/tests/Makefile.in | 2 +- dlls/d3dx10_38/tests/Makefile.in | 2 +- dlls/d3dx10_39/tests/Makefile.in | 2 +- dlls/d3dx10_40/tests/Makefile.in | 2 +- dlls/d3dx10_41/tests/Makefile.in | 2 +- dlls/d3dx10_42/tests/Makefile.in | 2 +- dlls/d3dx10_43/tests/Makefile.in | 2 +- dlls/d3dx10_43/tests/d3dx10.c | 378 ++++++++++++++++++++++++++++--- 12 files changed, 359 insertions(+), 41 deletions(-) diff --git a/dlls/d3dx10_33/tests/Makefile.in b/dlls/d3dx10_33/tests/Makefile.in index e193cccc2c6..ab6961da50a 100644 --- a/dlls/d3dx10_33/tests/Makefile.in +++ b/dlls/d3dx10_33/tests/Makefile.in @@ -1,6 +1,6 @@ EXTRADEFS = -DD3DX10_SDK_VERSION=33 TESTDLL = d3dx10_33.dll -IMPORTS = d3dx10_33 ole32 gdi32 +IMPORTS = d3dx10_33 ole32 gdi32 user32 PARENTSRC = ../../d3dx10_43/tests SOURCES = \ diff --git a/dlls/d3dx10_34/tests/Makefile.in b/dlls/d3dx10_34/tests/Makefile.in index e0dd116ed2f..889075450ed 100644 --- a/dlls/d3dx10_34/tests/Makefile.in +++ b/dlls/d3dx10_34/tests/Makefile.in @@ -1,6 +1,6 @@ EXTRADEFS = -DD3DX10_SDK_VERSION=34 TESTDLL = d3dx10_34.dll -IMPORTS = d3dx10_34 ole32 gdi32 +IMPORTS = d3dx10_34 ole32 gdi32 user32 PARENTSRC = ../../d3dx10_43/tests SOURCES = \ diff --git a/dlls/d3dx10_35/tests/Makefile.in b/dlls/d3dx10_35/tests/Makefile.in index 241132f2cbf..0cd6a76da47 100644 --- a/dlls/d3dx10_35/tests/Makefile.in +++ b/dlls/d3dx10_35/tests/Makefile.in @@ -1,6 +1,6 @@ EXTRADEFS = -DD3DX10_SDK_VERSION=35 TESTDLL = d3dx10_35.dll -IMPORTS = d3dx10_35 ole32 gdi32 +IMPORTS = d3dx10_35 ole32 gdi32 user32 PARENTSRC = ../../d3dx10_43/tests SOURCES = \ diff --git a/dlls/d3dx10_36/tests/Makefile.in b/dlls/d3dx10_36/tests/Makefile.in index 33d122e2ba6..8d4ab23665c 100644 --- a/dlls/d3dx10_36/tests/Makefile.in +++ b/dlls/d3dx10_36/tests/Makefile.in @@ -1,6 +1,6 @@ EXTRADEFS = -DD3DX10_SDK_VERSION=36 TESTDLL = d3dx10_36.dll -IMPORTS = d3dx10_36 ole32 gdi32 +IMPORTS = d3dx10_36 ole32 gdi32 user32 PARENTSRC = ../../d3dx10_43/tests SOURCES = \ diff --git a/dlls/d3dx10_37/tests/Makefile.in b/dlls/d3dx10_37/tests/Makefile.in index 10edb074946..0543c42ac8f 100644 --- a/dlls/d3dx10_37/tests/Makefile.in +++ b/dlls/d3dx10_37/tests/Makefile.in @@ -1,6 +1,6 @@ EXTRADEFS = -DD3DX10_SDK_VERSION=37 TESTDLL = d3dx10_37.dll -IMPORTS = d3dx10_37 ole32 gdi32 +IMPORTS = d3dx10_37 ole32 gdi32 user32 PARENTSRC = ../../d3dx10_43/tests SOURCES = \ diff --git a/dlls/d3dx10_38/tests/Makefile.in b/dlls/d3dx10_38/tests/Makefile.in index f2ec875d965..fe7047b6040 100644 --- a/dlls/d3dx10_38/tests/Makefile.in +++ b/dlls/d3dx10_38/tests/Makefile.in @@ -1,6 +1,6 @@ EXTRADEFS = -DD3DX10_SDK_VERSION=38 TESTDLL = d3dx10_38.dll -IMPORTS = d3dx10_38 ole32 gdi32 +IMPORTS = d3dx10_38 ole32 gdi32 user32 PARENTSRC = ../../d3dx10_43/tests SOURCES = \ diff --git a/dlls/d3dx10_39/tests/Makefile.in b/dlls/d3dx10_39/tests/Makefile.in index 5cf915fd403..c5b5475bb90 100644 --- a/dlls/d3dx10_39/tests/Makefile.in +++ b/dlls/d3dx10_39/tests/Makefile.in @@ -1,6 +1,6 @@ EXTRADEFS = -DD3DX10_SDK_VERSION=39 TESTDLL = d3dx10_39.dll -IMPORTS = d3dx10_39 ole32 gdi32 +IMPORTS = d3dx10_39 ole32 gdi32 user32 PARENTSRC = ../../d3dx10_43/tests SOURCES = \ diff --git a/dlls/d3dx10_40/tests/Makefile.in b/dlls/d3dx10_40/tests/Makefile.in index 482f4c9fa9e..5b2bb8c0779 100644 --- a/dlls/d3dx10_40/tests/Makefile.in +++ b/dlls/d3dx10_40/tests/Makefile.in @@ -1,6 +1,6 @@ EXTRADEFS = -DD3DX10_SDK_VERSION=40 TESTDLL = d3dx10_40.dll -IMPORTS = d3dx10_40 ole32 gdi32 +IMPORTS = d3dx10_40 ole32 gdi32 user32 PARENTSRC = ../../d3dx10_43/tests SOURCES = \ diff --git a/dlls/d3dx10_41/tests/Makefile.in b/dlls/d3dx10_41/tests/Makefile.in index b7ceb0818d2..37a7b5e4468 100644 --- a/dlls/d3dx10_41/tests/Makefile.in +++ b/dlls/d3dx10_41/tests/Makefile.in @@ -1,6 +1,6 @@ EXTRADEFS = -DD3DX10_SDK_VERSION=41 TESTDLL = d3dx10_41.dll -IMPORTS = d3dx10_41 ole32 gdi32 +IMPORTS = d3dx10_41 ole32 gdi32 user32 PARENTSRC = ../../d3dx10_43/tests SOURCES = \ diff --git a/dlls/d3dx10_42/tests/Makefile.in b/dlls/d3dx10_42/tests/Makefile.in index f04547f202b..6f433fda736 100644 --- a/dlls/d3dx10_42/tests/Makefile.in +++ b/dlls/d3dx10_42/tests/Makefile.in @@ -1,6 +1,6 @@ EXTRADEFS = -DD3DX10_SDK_VERSION=42 TESTDLL = d3dx10_42.dll -IMPORTS = d3dx10_42 ole32 gdi32 +IMPORTS = d3dx10_42 ole32 gdi32 user32 PARENTSRC = ../../d3dx10_43/tests SOURCES = \ diff --git a/dlls/d3dx10_43/tests/Makefile.in b/dlls/d3dx10_43/tests/Makefile.in index a3579db263b..abe223af37d 100644 --- a/dlls/d3dx10_43/tests/Makefile.in +++ b/dlls/d3dx10_43/tests/Makefile.in @@ -1,6 +1,6 @@ EXTRADEFS = -DD3DX10_SDK_VERSION=43 TESTDLL = d3dx10_43.dll -IMPORTS = d3dx10 ole32 gdi32 +IMPORTS = d3dx10 ole32 gdi32 user32 SOURCES = \ d3dx10.c diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index fd5e8853daa..fa5cf743b7a 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -25,6 +25,210 @@ #include <stdint.h> #include <assert.h> +#define SWAPCHAIN_FLAG_SHADER_INPUT 0x1 + +struct swapchain_desc +{ + BOOL windowed; + unsigned int buffer_count; + unsigned int width, height; + DXGI_SWAP_EFFECT swap_effect; + DWORD flags; +}; + +static IDXGISwapChain *create_swapchain(ID3D10Device *device, HWND window, + const struct swapchain_desc *swapchain_desc) +{ + IDXGISwapChain *swapchain; + DXGI_SWAP_CHAIN_DESC dxgi_desc; + IDXGIDevice *dxgi_device; + IDXGIAdapter *adapter; + IDXGIFactory *factory; + HRESULT hr; + + hr = ID3D10Device_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device); + ok(hr == S_OK, "Failed to get DXGI device, hr %#lx.\n", hr); + hr = IDXGIDevice_GetAdapter(dxgi_device, &adapter); + ok(hr == S_OK, "Failed to get adapter, hr %#lx.\n", hr); + IDXGIDevice_Release(dxgi_device); + hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory); + ok(hr == S_OK, "Failed to get factory, hr %#lx.\n", hr); + IDXGIAdapter_Release(adapter); + + dxgi_desc.BufferDesc.Width = 640; + dxgi_desc.BufferDesc.Height = 480; + dxgi_desc.BufferDesc.RefreshRate.Numerator = 60; + dxgi_desc.BufferDesc.RefreshRate.Denominator = 1; + dxgi_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + dxgi_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + dxgi_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + dxgi_desc.SampleDesc.Count = 1; + dxgi_desc.SampleDesc.Quality = 0; + dxgi_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + dxgi_desc.BufferCount = 1; + dxgi_desc.OutputWindow = window; + dxgi_desc.Windowed = TRUE; + dxgi_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + dxgi_desc.Flags = 0; + + if (swapchain_desc) + { + dxgi_desc.Windowed = swapchain_desc->windowed; + dxgi_desc.SwapEffect = swapchain_desc->swap_effect; + dxgi_desc.BufferCount = swapchain_desc->buffer_count; + if (swapchain_desc->width) + dxgi_desc.BufferDesc.Width = swapchain_desc->width; + if (swapchain_desc->height) + dxgi_desc.BufferDesc.Height = swapchain_desc->height; + + if (swapchain_desc->flags & SWAPCHAIN_FLAG_SHADER_INPUT) + dxgi_desc.BufferUsage |= DXGI_USAGE_SHADER_INPUT; + } + + hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &dxgi_desc, &swapchain); + ok(hr == S_OK, "Failed to create swapchain, hr %#lx.\n", hr); + IDXGIFactory_Release(factory); + + return swapchain; +} + +struct d3d10_test_context +{ + ID3D10Device *device; + HWND window; + IDXGISwapChain *swapchain; + ID3D10Texture2D *backbuffer; + ID3D10RenderTargetView *backbuffer_rtv; + + ID3D10InputLayout *input_layout; + ID3D10VertexShader *vs; + const DWORD *vs_code; + ID3D10Buffer *vs_cb; + ID3D10Buffer *vb; + + ID3D10PixelShader *ps; + ID3D10Buffer *ps_cb; +}; + +static void set_viewport(ID3D10Device *device, int x, int y, + unsigned int width, unsigned int height, float min_depth, float max_depth) +{ + D3D10_VIEWPORT vp; + + vp.TopLeftX = x; + vp.TopLeftY = y; + vp.Width = width; + vp.Height = height; + vp.MinDepth = min_depth; + vp.MaxDepth = max_depth; + + ID3D10Device_RSSetViewports(device, 1, &vp); +} + +static ID3D10Device *create_device(void) +{ + ID3D10Device *device; + HMODULE d3d10_mod = LoadLibraryA("d3d10.dll"); + HRESULT (WINAPI *pD3D10CreateDevice)(IDXGIAdapter *, D3D10_DRIVER_TYPE, HMODULE, UINT, UINT, ID3D10Device **); + + if (!d3d10_mod) + { + win_skip("d3d10.dll not present\n"); + return NULL; + } + + pD3D10CreateDevice = (void *)GetProcAddress(d3d10_mod, "D3D10CreateDevice"); + if (SUCCEEDED(pD3D10CreateDevice(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_SDK_VERSION, &device))) + return device; + if (SUCCEEDED(pD3D10CreateDevice(NULL, D3D10_DRIVER_TYPE_WARP, NULL, 0, D3D10_SDK_VERSION, &device))) + return device; + if (SUCCEEDED(pD3D10CreateDevice(NULL, D3D10_DRIVER_TYPE_REFERENCE, NULL, 0, D3D10_SDK_VERSION, &device))) + return device; + + return NULL; +} + +#define init_test_context(a) init_test_context_(__LINE__, a, NULL) +#define init_test_context_ext(a, b) init_test_context_(__LINE__, a, b) +static BOOL init_test_context_(unsigned int line, struct d3d10_test_context *context, + const struct swapchain_desc *swapchain_desc) +{ + unsigned int rt_width, rt_height; + HRESULT hr; + RECT rect; + + memset(context, 0, sizeof(*context)); + + if (!(context->device = create_device())) + { + skip_(__FILE__, line)("Failed to create device.\n"); + return FALSE; + } + + rt_width = swapchain_desc && swapchain_desc->width ? swapchain_desc->width : 640; + rt_height = swapchain_desc && swapchain_desc->height ? swapchain_desc->height : 480; + + SetRect(&rect, 0, 0, rt_width, rt_height); + AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE); + context->window = CreateWindowA("static", "d3dx10_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, NULL); + context->swapchain = create_swapchain(context->device, context->window, swapchain_desc); + hr = IDXGISwapChain_GetBuffer(context->swapchain, 0, &IID_ID3D10Texture2D, (void **)&context->backbuffer); + ok_(__FILE__, line)(hr == S_OK, "Failed to get backbuffer, hr %#lx.\n", hr); + + hr = ID3D10Device_CreateRenderTargetView(context->device, (ID3D10Resource *)context->backbuffer, + NULL, &context->backbuffer_rtv); + ok_(__FILE__, line)(hr == S_OK, "Failed to create rendertarget view, hr %#lx.\n", hr); + + ID3D10Device_OMSetRenderTargets(context->device, 1, &context->backbuffer_rtv, NULL); + + set_viewport(context->device, 0, 0, rt_width, rt_height, 0.0f, 1.0f); + + return TRUE; +} + +#define release_test_context(c) release_test_context_(__LINE__, c) +static void release_test_context_(unsigned int line, struct d3d10_test_context *context) +{ + ULONG ref; + + if (context->input_layout) + ID3D10InputLayout_Release(context->input_layout); + if (context->vs) + ID3D10VertexShader_Release(context->vs); + if (context->vs_cb) + ID3D10Buffer_Release(context->vs_cb); + if (context->vb) + ID3D10Buffer_Release(context->vb); + if (context->ps) + ID3D10PixelShader_Release(context->ps); + if (context->ps_cb) + ID3D10Buffer_Release(context->ps_cb); + + ID3D10RenderTargetView_Release(context->backbuffer_rtv); + ID3D10Texture2D_Release(context->backbuffer); + IDXGISwapChain_Release(context->swapchain); + DestroyWindow(context->window); + + ref = ID3D10Device_Release(context->device); + ok_(__FILE__, line)(!ref, "Device has %lu references left.\n", ref); +} + +static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff) +{ + unsigned int diff = x > y ? x - y : y - x; + + return diff <= max_diff; +} + +static BOOL compare_color(DWORD c1, DWORD c2, BYTE max_diff) +{ + return compare_uint(c1 & 0xff, c2 & 0xff, max_diff) + && compare_uint((c1 >> 8) & 0xff, (c2 >> 8) & 0xff, max_diff) + && compare_uint((c1 >> 16) & 0xff, (c2 >> 16) & 0xff, max_diff) + && compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff); +} + static const char *debug_d3dx10_filter(uint32_t filter_flags) { static const char *filter_types[] = { "", "D3DX10_FILTER_NONE", "D3DX10_FILTER_POINT", "D3DX10_FILTER_LINEAR", @@ -2370,13 +2574,6 @@ static ULONG get_refcount(void *iface) return IUnknown_Release(unknown); } -static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff) -{ - unsigned int diff = x > y ? x - y : y - x; - - return diff <= max_diff; -} - static BOOL compare_float(float f, float g, unsigned int ulps) { int x = *(int *)&f; @@ -2435,29 +2632,6 @@ static BOOL delete_file(const WCHAR *filename) return DeleteFileW(path); } -static ID3D10Device *create_device(void) -{ - ID3D10Device *device; - HMODULE d3d10_mod = LoadLibraryA("d3d10.dll"); - HRESULT (WINAPI *pD3D10CreateDevice)(IDXGIAdapter *, D3D10_DRIVER_TYPE, HMODULE, UINT, UINT, ID3D10Device **); - - if (!d3d10_mod) - { - win_skip("d3d10.dll not present\n"); - return NULL; - } - - pD3D10CreateDevice = (void *)GetProcAddress(d3d10_mod, "D3D10CreateDevice"); - if (SUCCEEDED(pD3D10CreateDevice(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_SDK_VERSION, &device))) - return device; - if (SUCCEEDED(pD3D10CreateDevice(NULL, D3D10_DRIVER_TYPE_WARP, NULL, 0, D3D10_SDK_VERSION, &device))) - return device; - if (SUCCEEDED(pD3D10CreateDevice(NULL, D3D10_DRIVER_TYPE_REFERENCE, NULL, 0, D3D10_SDK_VERSION, &device))) - return device; - - return NULL; -} - static HMODULE create_resource_module(const WCHAR *filename, const void *data, unsigned int size) { WCHAR resource_module_path[MAX_PATH], current_module_path[MAX_PATH]; @@ -2824,6 +2998,11 @@ static uint32_t get_readback_u32(struct resource_readback *rb, uint32_t x, uint3 return *(uint32_t *)get_readback_data(rb, x, y, 0, sizeof(uint32_t)); } +static uint32_t get_readback_color(struct resource_readback *rb, unsigned int x, unsigned int y) +{ + return get_readback_u32(rb, x, y); +} + static void release_resource_readback(struct resource_readback *rb) { switch (rb->dimension) @@ -2847,6 +3026,18 @@ static void release_resource_readback(struct resource_readback *rb) ID3D10Resource_Release(rb->resource); } +static uint32_t get_texture_color(ID3D10Texture2D *texture, unsigned int x, unsigned int y) +{ + struct resource_readback rb; + uint32_t color; + + get_texture_readback(texture, 0, &rb); + color = get_readback_color(&rb, x, y); + release_resource_readback(&rb); + + return color; +} + static inline BOOL check_readback_pixel_4bpp_rgba(const void *got, const void *expected, uint32_t max_diff) { const uint32_t c1 = *(const uint32_t *)got; @@ -7886,6 +8077,132 @@ static void test_sprite_save_state(void) ok(!refcount, "Unexpected refcount.\n"); } +static void test_sprite_render(void) +{ + static const DWORD texture_data[] = + { + 0xff0000ff, 0xff0000ff, 0xffff00ff, 0xffff00ff, + 0xff0000ff, 0xff0000ff, 0xffff00ff, 0xffff00ff, + 0xffff0000, 0xffff0000, 0xff00ffff, 0xff00ffff, + 0xffff0000, 0xffff0000, 0xff00ffff, 0xff00ffff, + }; + + struct d3d10_test_context test_context; + D3D10_SUBRESOURCE_DATA resource_data; + D3D10_TEXTURE2D_DESC texture_desc; + ID3D10ShaderResourceView *srv; + D3DX10_SPRITE sprite_desc; + ID3D10Texture2D *texture; + ID3DX10Sprite *sprite; + ID3D10Device *device; + unsigned int color; + float clear[4]; + HRESULT hr; + + if (!init_test_context(&test_context)) + return; + + device = test_context.device; + + texture_desc.Width = 4; + texture_desc.Height = 4; + texture_desc.MipLevels = 1; + texture_desc.ArraySize = 1; + texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + texture_desc.SampleDesc.Count = 1; + texture_desc.SampleDesc.Quality = 0; + texture_desc.Usage = D3D10_USAGE_DEFAULT; + texture_desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + texture_desc.CPUAccessFlags = 0; + texture_desc.MiscFlags = 0; + + resource_data.pSysMem = texture_data; + resource_data.SysMemPitch = 16; + resource_data.SysMemSlicePitch = 0; + hr = ID3D10Device_CreateTexture2D(device, &texture_desc, &resource_data, &texture); + ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr); + + hr = ID3D10Device_CreateShaderResourceView(device, (ID3D10Resource *)texture, NULL, &srv); + ok(hr == S_OK, "Failed to create srv, hr %#lx.\n", hr); + + hr = D3DX10CreateSprite(device, 0, &sprite); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = ID3DX10Sprite_Begin(sprite, 0); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + clear[0] = clear[1] = clear[2] = clear[3] = 1.0f; + ID3D10Device_ClearRenderTargetView(device, test_context.backbuffer_rtv, clear); + + /* Each color to its quadrant. */ + D3DXMatrixTranslation(&sprite_desc.matWorld, -0.5f, 0.5f, 0.0f); + sprite_desc.TexCoord.x = 0.0f; + sprite_desc.TexCoord.y = 0.0f; + sprite_desc.TexSize.x = 0.25f; + sprite_desc.TexSize.y = 0.25f; + sprite_desc.ColorModulate.r = 1.0f; + sprite_desc.ColorModulate.g = 1.0f; + sprite_desc.ColorModulate.b = 1.0f; + sprite_desc.ColorModulate.a = 1.0f; + sprite_desc.pTexture = srv; + sprite_desc.TextureIndex = 0; + + hr = ID3DX10Sprite_DrawSpritesBuffered(sprite, &sprite_desc, 1); + todo_wine + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + D3DXMatrixTranslation(&sprite_desc.matWorld, 0.5f, 0.5f, 0.0f); + sprite_desc.TexCoord.x = 0.7f; + sprite_desc.TexCoord.y = 0.0f; + sprite_desc.TexSize.x = 0.25f; + sprite_desc.TexSize.y = 0.25f; + hr = ID3DX10Sprite_DrawSpritesBuffered(sprite, &sprite_desc, 1); + todo_wine + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + D3DXMatrixTranslation(&sprite_desc.matWorld, -0.5f, -0.5f, 0.0f); + sprite_desc.TexCoord.x = 0.0f; + sprite_desc.TexCoord.y = 0.6f; + sprite_desc.TexSize.x = 0.25f; + sprite_desc.TexSize.y = 0.25f; + hr = ID3DX10Sprite_DrawSpritesBuffered(sprite, &sprite_desc, 1); + todo_wine + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + D3DXMatrixTranslation(&sprite_desc.matWorld, 0.5f, -0.5f, 0.0f); + sprite_desc.TexCoord.x = 0.7f; + sprite_desc.TexCoord.y = 0.7f; + sprite_desc.TexSize.x = 0.5f; + sprite_desc.TexSize.y = 0.5f; + hr = ID3DX10Sprite_DrawSpritesBuffered(sprite, &sprite_desc, 1); + todo_wine + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = ID3DX10Sprite_Flush(sprite); + todo_wine + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = ID3DX10Sprite_End(sprite); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + color = get_texture_color(test_context.backbuffer, 160, 120); + todo_wine + ok(compare_color(color, 0xff0000ff, 0), "Got unexpected color 0x%08x.\n", color); + color = get_texture_color(test_context.backbuffer, 480, 120); + todo_wine + ok(compare_color(color, 0xffff00ff, 0), "Got unexpected color 0x%08x.\n", color); + color = get_texture_color(test_context.backbuffer, 160, 360); + todo_wine + ok(compare_color(color, 0xffff0000, 0), "Got unexpected color 0x%08x.\n", color); + color = get_texture_color(test_context.backbuffer, 480, 360); + todo_wine + ok(compare_color(color, 0xff00ffff, 0), "Got unexpected color 0x%08x.\n", color); + + ID3DX10Sprite_Release(sprite); + ID3D10Texture2D_Release(texture); + ID3D10ShaderResourceView_Release(srv); + release_test_context(&test_context); +} + static void test_create_effect_from_memory(void) { D3D10_EFFECT_DESC desc; @@ -8240,6 +8557,7 @@ START_TEST(d3dx10) test_font(); test_sprite(); test_sprite_save_state(); + test_sprite_render(); test_create_effect_from_memory(); test_create_effect_from_file(); test_create_effect_from_resource(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11674
Those are old test failures. The d3dx10_36 crash (?) does not happen for me locally, so no idea there. They do crash occasionally according to the tests page. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11674#note_148931
Matteo Bruni (@Mystral) commented about dlls/d3dx10_43/sprite.c:
static HRESULT WINAPI d3dx10_sprite_Begin(ID3DX10Sprite *iface, UINT flags) { + struct d3dx10_sprite *sprite = impl_from_ID3DX10Sprite(iface); + FIXME("iface %p, flags %#x stub!\n", iface, flags);
What else is missing before we can turn this into a `TRACE()`? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11674#note_149354
Matteo Bruni (@Mystral) commented about dlls/d3dx10_43/sprite.c:
+ return E_FAIL; + return E_NOTIMPL; }
static HRESULT WINAPI d3dx10_sprite_End(ID3DX10Sprite *iface) { + struct d3dx10_sprite *sprite = impl_from_ID3DX10Sprite(iface); + FIXME("iface %p stub!\n", iface);
- return E_NOTIMPL; + if (!(sprite->flags & D3DX10_SPRITE_READY)) + return E_FAIL; + + sprite->flags = 0; Not that it matters at this point, but maybe we want to remove only the `D3DX10_SPRITE_READY` flag here.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11674#note_149355
Matteo Bruni (@Mystral) commented about dlls/d3dx10_43/sprite.c:
{ struct d3dx10_sprite *sprite = impl_from_ID3DX10Sprite(iface);
FIXME("iface %p stub!\n", iface); Similarly here, what's still missing before we can drop the "stub!" part?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11674#note_149356
Matteo Bruni (@Mystral) commented about include/d3dx10math.h:
D3DXCOLOR *D3DXColorScale(D3DXCOLOR *out, D3DXCOLOR c, float s); D3DXCOLOR *D3DXColorSubtract(D3DXCOLOR *out, D3DXCOLOR c1, D3DXCOLOR c2); D3DX_CPU_OPTIMIZATION WINAPI D3DXCpuOptimizations(BOOL enable); +D3DXMATRIX *WINAPI D3DXMatrixTranslation(D3DXMATRIX *m, float x, float y, float z); +D3DXMATRIX *WINAPI D3DXMatrixPerspectiveFovLH(D3DXMATRIX *m, float fovy, float aspect, float zn, float zf); +D3DXMATRIX *WINAPI D3DXMatrixTranslation(D3DXMATRIX *m, float x, float y, float z); This looks like a duplicate from 2 lines above.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11674#note_149357
Matteo Bruni (@Mystral) commented about include/d3dx10math.h:
D3DXCOLOR *D3DXColorScale(D3DXCOLOR *out, D3DXCOLOR c, float s); D3DXCOLOR *D3DXColorSubtract(D3DXCOLOR *out, D3DXCOLOR c1, D3DXCOLOR c2); D3DX_CPU_OPTIMIZATION WINAPI D3DXCpuOptimizations(BOOL enable); +D3DXMATRIX *WINAPI D3DXMatrixTranslation(D3DXMATRIX *m, float x, float y, float z); +D3DXMATRIX *WINAPI D3DXMatrixPerspectiveFovLH(D3DXMATRIX *m, float fovy, float aspect, float zn, float zf); +D3DXMATRIX *WINAPI D3DXMatrixTranslation(D3DXMATRIX *m, float x, float y, float z); +D3DXMATRIX *WINAPI D3DXMatrixRotationX(D3DXMATRIX *m, float angle); +D3DXMATRIX *WINAPI D3DXMatrixRotationY(D3DXMATRIX *m, float angle); +D3DXMATRIX *WINAPI D3DXMatrixRotationZ(D3DXMATRIX *m, float angle); +D3DXMATRIX *WINAPI D3DXMatrixPerspectiveLH(D3DXMATRIX *m, float w, float h, float zn, float zf); +D3DXVECTOR4 *WINAPI D3DXVec2TransformArray(D3DXVECTOR4 *pout, UINT outstride, const D3DXVECTOR2 *pv, + UINT vstride, const D3DXMATRIX *pm, UINT n); Very much a nitpick, but we usually drop the Hungarian notation `p` in front of pointer arguments.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11674#note_149358
Matteo Bruni (@Mystral) commented about dlls/d3dx10_43/sprite.c:
return E_FAIL;
+ if (!d3dx_array_reserve((void **)&sprite->buffer.sprites, &sprite->buffer.capacity, + sprite->buffer.count + count, sizeof(*sprite->buffer.sprites))) + { + return E_OUTOFMEMORY; + } + + for (unsigned int i = 0; i < count; ++i) + { + sprite->buffer.sprites[sprite->buffer.count++] = sprites[i]; + if (sprite->flags & D3DX10_SPRITE_ADDREF_TEXTURES) + ID3D10ShaderResourceView_AddRef(sprites[i].pTexture); + } + return E_NOTIMPL;
Does it make sense to `return S_OK;` now, or is it too early? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11674#note_149359
Matteo Bruni (@Mystral) commented about dlls/d3dx10_43/tests/d3dx10.c:
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + D3DXMatrixTranslation(&sprite_desc.matWorld, 0.5f, -0.5f, 0.0f); + sprite_desc.TexCoord.x = 0.7f; + sprite_desc.TexCoord.y = 0.7f; + sprite_desc.TexSize.x = 0.5f; + sprite_desc.TexSize.y = 0.5f; + hr = ID3DX10Sprite_DrawSpritesBuffered(sprite, &sprite_desc, 1); + todo_wine + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = ID3DX10Sprite_Flush(sprite); + todo_wine + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = ID3DX10Sprite_End(sprite); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); I'm curious whether `Flush()` is actually necessary or not (for context, in d3dx9 it isn't, it's implied by `End()`).
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11674#note_149360
gitlab decided that I can't update my comments before publishing them, apologies for any mistakes. Nothing much anyway, the only one that made me not approve right away is the duplicate line in d3dx10math.h. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11674#note_149361
On Thu Aug 20 10:27:26 2026 +0000, Matteo Bruni wrote:
Not that it matters at this point, but maybe we want to remove only the `D3DX10_SPRITE_READY` flag here. Flags are reset on each Begin() so I don't see a reason to retain them.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11674#note_149395
On Thu Aug 20 10:27:26 2026 +0000, Matteo Bruni wrote:
I'm curious whether `Flush()` is actually necessary or not (for context, in d3dx9 it isn't, it's implied by `End()`). It is implied, but it's there to check Flush-End sequence regarding return values, nothing else.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11674#note_149396
On Thu Aug 20 10:27:26 2026 +0000, Matteo Bruni wrote:
Similarly here, what's still missing before we can drop the "stub!" part? Rendering is missing.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11674#note_149399
On Thu Aug 20 14:13:15 2026 +0000, Nikolay Sivov wrote:
Rendering is missing. It doesn't matter, but rendering is presumably going to happen in `d3dx10_sprite_flush()`, so there is possibly nothing else to change in `d3dx10_sprite_Flush()` aside from dropping the FIXME(), which is kinda easy to forget. Again, nothing of importance.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11674#note_149400
participants (3)
-
Matteo Bruni (@Mystral) -
Nikolay Sivov -
Nikolay Sivov (@nsivov)