From: Stefan Dösinger Subject: [PATCH 3/5] ddraw: Fix offscreen flag handling in TransformVertices. Message-Id: <1472504488-6747-3-git-send-email-stefandoesinger@gmx.at> Date: Mon, 29 Aug 2016 22:01:26 +0100 In-Reply-To: <1472504488-6747-1-git-send-email-stefandoesinger@gmx.at> References: <1472504488-6747-1-git-send-email-stefandoesinger@gmx.at> Signed-off-by: Stefan Dösinger --- dlls/ddraw/tests/ddraw1.c | 32 ++++++++++++++++++++++++-------- dlls/ddraw/viewport.c | 34 +++++++++++++--------------------- 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c index cff569b..fdec0ec 100644 --- a/dlls/ddraw/tests/ddraw1.c +++ b/dlls/ddraw/tests/ddraw1.c @@ -9341,12 +9341,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; @@ -9366,17 +9361,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]); diff --git a/dlls/ddraw/viewport.c b/dlls/ddraw/viewport.c index 8a42faf..d857dc3 100644 --- a/dlls/ddraw/viewport.c +++ b/dlls/ddraw/viewport.c @@ -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"); -- 2.7.3