Commit 5a8e430b authored by Matteo Bruni's avatar Matteo Bruni Committed by Alexandre Julliard

ddraw: Support drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffers.

parent 695dbca9
......@@ -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
......
......@@ -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();
}
......@@ -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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment