[PATCH 5/5] ddraw: Support drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffers.
Henri Verbeet
hverbeet at codeweavers.com
Mon Dec 17 13:29:25 CST 2018
From: Matteo Bruni <mbruni at codeweavers.com>
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45279
Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
dlls/ddraw/device.c | 44 +++++++++++++++++++-
dlls/ddraw/tests/ddraw4.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++
dlls/ddraw/tests/ddraw7.c | 93 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 236 insertions(+), 1 deletion(-)
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c
index 0d48c7d704e..48803f8f937 100644
--- a/dlls/ddraw/device.c
+++ b/dlls/ddraw/device.c
@@ -4275,8 +4275,11 @@ static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVE
{
struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
- HRESULT hr;
+ struct wined3d_resource *wined3d_resource;
+ struct wined3d_map_desc wined3d_map_desc;
+ struct wined3d_box wined3d_box = {0};
DWORD stride;
+ HRESULT hr;
TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
iface, primitive_type, vb, start_vertex, vertex_count, flags);
@@ -4289,6 +4292,26 @@ static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVE
stride = get_flexible_vertex_size(vb_impl->fvf);
+ if (vb_impl->Caps & D3DVBCAPS_SYSTEMMEMORY)
+ {
+ TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawPrimitive().\n");
+ wined3d_mutex_lock();
+ wined3d_resource = wined3d_buffer_get_resource(vb_impl->wined3d_buffer);
+ wined3d_box.left = start_vertex * stride;
+ wined3d_box.right = wined3d_box.left + vertex_count * stride;
+ if (FAILED(hr = wined3d_resource_map(wined3d_resource, 0, &wined3d_map_desc,
+ &wined3d_box, WINED3D_MAP_READ)))
+ {
+ wined3d_mutex_unlock();
+ return D3DERR_VERTEXBUFFERLOCKED;
+ }
+ hr = d3d_device7_DrawPrimitive(iface, primitive_type, vb_impl->fvf, wined3d_map_desc.data,
+ vertex_count, flags);
+ wined3d_resource_unmap(wined3d_resource, 0);
+ wined3d_mutex_unlock();
+ return hr;
+ }
+
wined3d_mutex_lock();
wined3d_device_set_vertex_declaration(device->wined3d_device, vb_impl->wined3d_declaration);
if (FAILED(hr = wined3d_device_set_stream_source(device->wined3d_device,
@@ -4366,6 +4389,7 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
DWORD stride = get_flexible_vertex_size(vb_impl->fvf);
+ struct wined3d_resource *wined3d_resource;
struct wined3d_map_desc wined3d_map_desc;
struct wined3d_box wined3d_box = {0};
struct wined3d_resource *ib;
@@ -4382,6 +4406,24 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
return D3D_OK;
}
+ if (vb_impl->Caps & D3DVBCAPS_SYSTEMMEMORY)
+ {
+ TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawIndexedPrimitive().\n");
+ wined3d_mutex_lock();
+ wined3d_resource = wined3d_buffer_get_resource(vb_impl->wined3d_buffer);
+ if (FAILED(hr = wined3d_resource_map(wined3d_resource, 0, &wined3d_map_desc,
+ &wined3d_box, WINED3D_MAP_READ)))
+ {
+ wined3d_mutex_unlock();
+ return D3DERR_VERTEXBUFFERLOCKED;
+ }
+ hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, vb_impl->fvf, wined3d_map_desc.data,
+ start_vertex + vertex_count, indices, index_count, flags);
+ wined3d_resource_unmap(wined3d_resource, 0);
+ wined3d_mutex_unlock();
+ return hr;
+ }
+
/* Steps:
* 1) Upload the indices to the index buffer
* 2) Set the index source
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index 443c78b6439..1c4841891e4 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -15373,6 +15373,105 @@ static void test_killfocus(void)
UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL));
}
+static void test_sysmem_draw(void)
+{
+ D3DRECT rect_full = {{0}, {0}, {640}, {480}};
+ IDirect3DViewport3 *viewport;
+ D3DVERTEXBUFFERDESC vb_desc;
+ IDirect3DVertexBuffer *vb;
+ IDirect3DDevice3 *device;
+ IDirectDrawSurface4 *rt;
+ IDirect3D3 *d3d;
+ D3DCOLOR color;
+ ULONG refcount;
+ HWND window;
+ HRESULT hr;
+ BYTE *data;
+
+ static const struct
+ {
+ struct vec3 position;
+ DWORD diffuse;
+ }
+ quad[] =
+ {
+ {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
+ {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
+ {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
+ {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
+ };
+ static WORD indices[] = {0, 1, 2, 3};
+
+ window = create_window();
+ ok(!!window, "Failed to create a window.\n");
+
+ if (!(device = create_device(window, DDSCL_NORMAL)))
+ {
+ skip("Failed to create a 3D device, skipping test.\n");
+ DestroyWindow(window);
+ return;
+ }
+
+ hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ viewport = create_viewport(device, 0, 0, 640, 480);
+ hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ vb_desc.dwSize = sizeof(vb_desc);
+ vb_desc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
+ vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
+ vb_desc.dwNumVertices = 4;
+ hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &vb, 0, NULL);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DVertexBuffer_Lock(vb, 0, (void **)&data, NULL);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ memcpy(data, quad, sizeof(quad));
+ hr = IDirect3DVertexBuffer_Unlock(vb);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DDevice3_BeginScene(device);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice3_EndScene(device);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ color = get_surface_color(rt, 320, 240);
+ ok(compare_color(color, 0x00007f7f, 1), "Got unexpected color 0x%08x.\n", color);
+
+ hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DDevice3_BeginScene(device);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, indices, 4, 0);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice3_EndScene(device);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ color = get_surface_color(rt, 320, 240);
+ ok(compare_color(color, 0x00007f7f, 1), "Got unexpected color 0x%08x.\n", color);
+
+ IDirect3DVertexBuffer_Release(vb);
+ IDirect3DViewport3_Release(viewport);
+ IDirectDrawSurface4_Release(rt);
+ IDirect3D3_Release(d3d);
+ refcount = IDirect3DDevice3_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ DestroyWindow(window);
+}
+
START_TEST(ddraw4)
{
DDDEVICEIDENTIFIER identifier;
@@ -15501,4 +15600,5 @@ START_TEST(ddraw4)
test_viewport();
test_find_device();
test_killfocus();
+ test_sysmem_draw();
}
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index 05151b06510..9ab8644191f 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -15088,6 +15088,98 @@ static void test_killfocus(void)
UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL));
}
+static void test_sysmem_draw(void)
+{
+ D3DVERTEXBUFFERDESC vb_desc;
+ IDirect3DVertexBuffer7 *vb;
+ IDirect3DDevice7 *device;
+ IDirectDrawSurface7 *rt;
+ IDirect3D7 *d3d;
+ D3DCOLOR colour;
+ ULONG refcount;
+ HWND window;
+ HRESULT hr;
+ BYTE *data;
+
+ static const struct
+ {
+ struct vec3 position;
+ DWORD diffuse;
+ }
+ quad[] =
+ {
+ {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
+ {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
+ {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
+ {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
+ };
+ static WORD indices[] = {0, 1, 2, 3};
+
+ window = create_window();
+ ok(!!window, "Failed to create a window.\n");
+
+ if (!(device = create_device(window, DDSCL_NORMAL)))
+ {
+ skip("Failed to create a 3D device, skipping test.\n");
+ DestroyWindow(window);
+ return;
+ }
+
+ hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ vb_desc.dwSize = sizeof(vb_desc);
+ vb_desc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
+ vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
+ vb_desc.dwNumVertices = 4;
+ hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DVertexBuffer7_Lock(vb, 0, (void **)&data, NULL);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ memcpy(data, quad, sizeof(quad));
+ hr = IDirect3DVertexBuffer7_Unlock(vb);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DDevice7_BeginScene(device);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice7_EndScene(device);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ colour = get_surface_color(rt, 320, 240);
+ ok(compare_color(colour, 0x00007f7f, 1), "Got unexpected colour 0x%08x.\n", colour);
+
+ hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DDevice7_BeginScene(device);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, indices, 4, 0);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice7_EndScene(device);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+ colour = get_surface_color(rt, 320, 240);
+ ok(compare_color(colour, 0x00007f7f, 1), "Got unexpected colour 0x%08x.\n", colour);
+
+ IDirect3DVertexBuffer7_Release(vb);
+ IDirectDrawSurface7_Release(rt);
+ IDirect3D7_Release(d3d);
+ refcount = IDirect3DDevice7_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ DestroyWindow(window);
+}
+
START_TEST(ddraw7)
{
DDDEVICEIDENTIFIER2 identifier;
@@ -15227,4 +15319,5 @@ START_TEST(ddraw7)
test_device_load();
test_color_vertex();
test_killfocus();
+ test_sysmem_draw();
}
--
2.11.0
More information about the wine-devel
mailing list