Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46371 Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2: Add a couple of comments.
dlls/d3d8/d3d8_private.h | 2 ++ dlls/d3d8/device.c | 29 +++++++++++++++++++++++++++-- dlls/d3d8/tests/visual.c | 24 +++++++++++++++++++++++- dlls/d3d8/vertexdeclaration.c | 2 +- 4 files changed, 53 insertions(+), 4 deletions(-)
diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h index 7c44f07c5ea..f3cab96f9d8 100644 --- a/dlls/d3d8/d3d8_private.h +++ b/dlls/d3d8/d3d8_private.h @@ -255,6 +255,8 @@ struct d3d8_vertex_declaration DWORD shader_handle; };
+UINT convert_to_wined3d_declaration(const DWORD *d3d8_elements, DWORD *d3d8_elements_size, + struct wined3d_vertex_element **wined3d_elements) DECLSPEC_HIDDEN; void d3d8_vertex_declaration_destroy(struct d3d8_vertex_declaration *declaration) DECLSPEC_HIDDEN; HRESULT d3d8_vertex_declaration_init(struct d3d8_vertex_declaration *declaration, struct d3d8_device *device, const DWORD *elements, DWORD shader_handle) DECLSPEC_HIDDEN; diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index d367f4200cc..2295b125506 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -2269,15 +2269,40 @@ static HRESULT WINAPI d3d8_device_GetCurrentTexturePalette(IDirect3DDevice8 *ifa static void d3d8_device_upload_sysmem_vertex_buffers(struct d3d8_device *device, unsigned int start_vertex, unsigned int vertex_count) { + struct wined3d_vertex_declaration *wined3d_decl; struct wined3d_box box = {0, 0, 0, 1, 0, 1}; + unsigned int i, offset, stride, map, count; + struct wined3d_vertex_element *elements; struct d3d8_vertexbuffer *d3d8_buffer; struct wined3d_resource *dst_resource; - unsigned int i, offset, stride, map; + struct d3d8_vertex_declaration *decl; struct wined3d_buffer *dst_buffer; struct wined3d_resource_desc desc; HRESULT hr;
- map = device->sysmem_vb; + if (!device->sysmem_vb) + return; + wined3d_decl = wined3d_device_get_vertex_declaration(device->wined3d_device); + if (!wined3d_decl) + return; + /* Make sure to only upload buffers that are used by the current draw: + * released buffers might still be bound as stream sources. */ + decl = wined3d_vertex_declaration_get_parent(wined3d_decl); + if (!decl->elements) + { + map = 1; + } + else + { + map = 0; + count = convert_to_wined3d_declaration(decl->elements, &decl->elements_size, &elements); + if (!count) + return; + for (i = 0; i < count; ++i) + map |= 1u << elements[i].input_slot; + heap_free(elements); + } + map &= device->sysmem_vb; while (map) { i = wined3d_bit_scan(&map); diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c index c405f8245ee..ac6a050f5fa 100644 --- a/dlls/d3d8/tests/visual.c +++ b/dlls/d3d8/tests/visual.c @@ -10698,6 +10698,29 @@ static void test_sysmem_draw(void) colour = getPixelColor(device, 320, 240); ok(color_match(colour, 0x00443322, 1), "Got unexpected colour 0x%08x.\n", colour);
+ /* Test that releasing but not unbinding a vertex buffer doesn't break. */ + hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice8_SetStreamSource(device, 0, vb, sizeof(*quad)); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice8_SetIndices(device, ib, 0); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + IDirect3DVertexBuffer8_Release(vb_s1); + + hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + hr = IDirect3DDevice8_BeginScene(device); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice8_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 4, 0, 2); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice8_EndScene(device); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + colour = getPixelColor(device, 320, 240); + ok(color_match(colour, 0x00007f7f, 1), "Got unexpected colour 0x%08x.\n", colour); + hr = IDirect3DDevice8_CreateTexture(device, 2, 2, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &texture); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); memset(&lr, 0, sizeof(lr)); @@ -10727,7 +10750,6 @@ static void test_sysmem_draw(void) ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
IDirect3DTexture8_Release(texture); - IDirect3DVertexBuffer8_Release(vb_s1); IDirect3DVertexBuffer8_Release(vb_s0); IDirect3DDevice8_DeleteVertexShader(device, vs); IDirect3DIndexBuffer8_Release(ib); diff --git a/dlls/d3d8/vertexdeclaration.c b/dlls/d3d8/vertexdeclaration.c index 709e04bace4..3c05101cb7f 100644 --- a/dlls/d3d8/vertexdeclaration.c +++ b/dlls/d3d8/vertexdeclaration.c @@ -249,7 +249,7 @@ wined3d_usage_lookup[] = };
/* TODO: find out where rhw (or positionT) is for declaration8 */ -static UINT convert_to_wined3d_declaration(const DWORD *d3d8_elements, DWORD *d3d8_elements_size, +UINT convert_to_wined3d_declaration(const DWORD *d3d8_elements, DWORD *d3d8_elements_size, struct wined3d_vertex_element **wined3d_elements) { struct wined3d_vertex_element *element;