ddraw: Fix offscreen flag handling in TransformVertices.

Signed-off-by: Stefan Dösinger <stefandoesinger@gmx.at>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Stefan Dösinger 2016-08-31 22:01:25 +01:00 committed by Alexandre Julliard
parent 606441e57e
commit 56e9a6e792
2 changed files with 37 additions and 29 deletions

View File

@ -9362,12 +9362,7 @@ static void test_transform_vertices(void)
}
/* Finally try to figure out how the DWORD dwOffscreen works.
* Apparently no vertex is offscreen with clipping off,
* and with clipping on the offscreen flag is set if only one vertex
* is transformed, and this vertex is offscreen.
*
* FIXME: This is wrong. It might be the logical AND of all
* output clip flags. */
* It is a logical AND of the vertices' dwFlags members. */
vp_data = vp_template;
vp_data.dwWidth = 5;
vp_data.dwHeight = 5;
@ -9387,17 +9382,38 @@ static void test_transform_vertices(void)
&transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
offscreen = 0xdeadbeef;
hr = IDirect3DViewport_TransformVertices(viewport, 2,
&transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
todo_wine ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
hr = IDirect3DViewport_TransformVertices(viewport, 3,
&transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
ok(!offscreen, "Offscreen is %x.\n", offscreen);
transformdata.lpIn = cliptest + 1;
hr = IDirect3DViewport_TransformVertices(viewport, 1,
&transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
ok(offscreen == (D3DCLIP_BACK | D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
transformdata.lpIn = cliptest + 2;
hr = IDirect3DViewport_TransformVertices(viewport, 1,
&transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
offscreen = 0xdeadbeef;
hr = IDirect3DViewport_TransformVertices(viewport, 2,
&transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
transformdata.lpIn = cliptest + 3;
hr = IDirect3DViewport_TransformVertices(viewport, 1,
&transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
ok(offscreen == (D3DCLIP_FRONT | D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
transformdata.lpIn = offscreentest;
transformdata.dwInSize = sizeof(offscreentest[0]);

View File

@ -372,8 +372,8 @@ static HRESULT WINAPI d3d_viewport_SetViewport(IDirect3DViewport3 *iface, D3DVIE
* dwVertexCount: The number of vertices to be transformed
* lpData: Pointer to the vertex data
* dwFlags: D3DTRANSFORM_CLIPPED or D3DTRANSFORM_UNCLIPPED
* lpOffScreen: Set to the clipping plane clipping the vertex, if only one
* vertex is transformed and clipping is on. 0 otherwise
* offscreen: Logical AND of the planes that clipped the vertices if clipping
* is on. 0 if clipping is off.
*
* Returns:
* D3D_OK on success
@ -391,7 +391,7 @@ struct transform_vertices_vertex
};
static HRESULT WINAPI d3d_viewport_TransformVertices(IDirect3DViewport3 *iface,
DWORD dwVertexCount, D3DTRANSFORMDATA *lpData, DWORD dwFlags, DWORD *lpOffScreen)
DWORD dwVertexCount, D3DTRANSFORMDATA *lpData, DWORD dwFlags, DWORD *offscreen)
{
struct d3d_viewport *viewport = impl_from_IDirect3DViewport3(iface);
D3DVIEWPORT vp = viewport->viewports.vp1;
@ -401,8 +401,8 @@ static HRESULT WINAPI d3d_viewport_TransformVertices(IDirect3DViewport3 *iface,
unsigned int i;
D3DHVERTEX *outH;
TRACE("iface %p, vertex_count %u, vertex_data %p, flags %#x, clip_plane %p.\n",
iface, dwVertexCount, lpData, dwFlags, lpOffScreen);
TRACE("iface %p, vertex_count %u, vertex_data %p, flags %#x, offscreen %p.\n",
iface, dwVertexCount, lpData, dwFlags, offscreen);
/* Tests on windows show that Windows crashes when this occurs,
* so don't return the (intuitive) return value
@ -428,6 +428,12 @@ static HRESULT WINAPI d3d_viewport_TransformVertices(IDirect3DViewport3 *iface,
multiply_matrix(&mat, &view_mat, &world_mat);
multiply_matrix(&mat, &viewport->active_device->legacy_projection, &mat);
/* The pointer is not tested against NULL on Windows. */
if (dwFlags & D3DTRANSFORM_CLIPPED)
*offscreen = ~0U;
else
*offscreen = 0;
outH = lpData->lpHOut;
for(i = 0; i < dwVertexCount; i++)
{
@ -460,6 +466,8 @@ static HRESULT WINAPI d3d_viewport_TransformVertices(IDirect3DViewport3 *iface,
if(z > 1.0)
outH[i].dwFlags |= D3DCLIP_BACK;
*offscreen &= outH[i].dwFlags;
if(outH[i].dwFlags)
{
/* Looks like native just drops the vertex, leaves whatever data
@ -485,22 +493,6 @@ static HRESULT WINAPI d3d_viewport_TransformVertices(IDirect3DViewport3 *iface,
out->payload = in->payload;
}
/* According to the d3d test, the offscreen flag is set only
* if exactly one vertex is transformed. It's not documented,
* but the test shows that the lpOffscreen flag is set to the
* flag combination of clipping planes that clips the vertex.
*
* If clipping is requested, Windows assumes that the offscreen
* param is a valid pointer.
*/
if(dwVertexCount == 1 && dwFlags & D3DTRANSFORM_CLIPPED)
{
*lpOffScreen = outH[0].dwFlags;
}
else if(*lpOffScreen)
{
*lpOffScreen = 0;
}
wined3d_mutex_unlock();
TRACE("All done\n");