Module: wine Branch: master Commit: 8bfc9e66143e8cb079432ba94187f4e9baeb08d9 URL: http://source.winehq.org/git/wine.git/?a=commit;h=8bfc9e66143e8cb079432ba941...
Author: Matteo Bruni mbruni@codeweavers.com Date: Tue Mar 14 00:09:57 2017 +0100
ddraw: Fix d3d6 version of ComputeSphereVisibility().
Signed-off-by: Matteo Bruni mbruni@codeweavers.com Signed-off-by: Henri Verbeet hverbeet@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ddraw/device.c | 122 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 88 insertions(+), 34 deletions(-)
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 6e212c9..772ce3e 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -4494,46 +4494,48 @@ static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface * *****************************************************************************/
-static DWORD in_plane(UINT idx, struct wined3d_vec4 p, D3DVECTOR center, D3DVALUE radius) +static DWORD in_plane(UINT idx, struct wined3d_vec4 p, D3DVECTOR center, D3DVALUE radius, BOOL equality) { float distance, norm;
norm = sqrtf(p.x * p.x + p.y * p.y + p.z * p.z); distance = (p.x * center.u1.x + p.y * center.u2.y + p.z * center.u3.z + p.w) / norm;
- if (fabs(distance) < radius) - return D3DSTATUS_CLIPUNIONLEFT << idx; - if (distance < -radius) - return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx; + if (equality) + { + if (fabs(distance) <= radius) + return D3DSTATUS_CLIPUNIONLEFT << idx; + if (distance <= -radius) + return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx; + } + else + { + if (fabs(distance) < radius) + return D3DSTATUS_CLIPUNIONLEFT << idx; + if (distance < -radius) + return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx; + } return 0; }
-static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface, - D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values) +static void prepare_clip_space_planes(struct d3d_device *device, struct wined3d_vec4 *plane) { - struct wined3d_vec4 plane[12]; - DWORD enabled_planes; D3DMATRIX m, temp; - HRESULT hr; - UINT i, j;
- TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n", - iface, centers, radii, sphere_count, flags, return_values); + /* We want the wined3d matrices since those include the legacy viewport + * transformation. */ + wined3d_mutex_lock(); + wined3d_device_get_transform(device->wined3d_device, + WINED3D_TS_WORLD, (struct wined3d_matrix *)&m);
- hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m); - if (hr != DD_OK) - return DDERR_INVALIDPARAMS; - hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp); - if (hr != DD_OK) - return DDERR_INVALIDPARAMS; + wined3d_device_get_transform(device->wined3d_device, + WINED3D_TS_VIEW, (struct wined3d_matrix *)&temp); multiply_matrix(&m, &temp, &m);
- hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp); - if (hr != DD_OK) - return DDERR_INVALIDPARAMS; + wined3d_device_get_transform(device->wined3d_device, + WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&temp); multiply_matrix(&m, &temp, &m); - - IDirect3DDevice7_GetRenderState(iface, D3DRENDERSTATE_CLIPPLANEENABLE, &enabled_planes); + wined3d_mutex_unlock();
/* Left plane. */ plane[0].x = m._14 + m._11; @@ -4570,33 +4572,85 @@ static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *ifac plane[5].y = m._24 - m._23; plane[5].z = m._34 - m._33; plane[5].w = m._44 - m._43; +}
- for (j = 6; j < 12; ++j) - IDirect3DDevice7_GetClipPlane(iface, j - 6, (D3DVALUE *)&plane[j]); +static void compute_sphere_visibility(struct wined3d_vec4 plane[12], DWORD enabled_planes, BOOL equality, + D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD *return_values) +{ + UINT i, j;
for (i = 0; i < sphere_count; ++i) { return_values[i] = 0; - for (j = 0; j < 6; ++j) - return_values[i] |= in_plane(j, plane[j], centers[i], radii[i]); - for (; j < 12; ++j) - if (enabled_planes & 1u << (j - 6)) - return_values[i] |= in_plane(j, plane[j], centers[i], radii[i]); + for (j = 0; j < 12; ++j) + if (enabled_planes & 1u << j) + return_values[i] |= in_plane(j, plane[j], centers[i], radii[i], equality); } +} + +static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface, + D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values) +{ + struct wined3d_vec4 plane[12]; + DWORD enabled_planes = 0x3f; + DWORD user_clip_planes; + UINT j; + + TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n", + iface, centers, radii, sphere_count, flags, return_values); + + prepare_clip_space_planes(impl_from_IDirect3DDevice7(iface), plane);
+ IDirect3DDevice7_GetRenderState(iface, D3DRENDERSTATE_CLIPPLANEENABLE, &user_clip_planes); + enabled_planes |= user_clip_planes << 6; + for (j = 6; j < 12; ++j) + IDirect3DDevice7_GetClipPlane(iface, j - 6, (D3DVALUE *)&plane[j]); + + compute_sphere_visibility(plane, enabled_planes, FALSE, centers, radii, sphere_count, return_values); return D3D_OK; }
static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface, D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values) { - struct d3d_device *device = impl_from_IDirect3DDevice3(iface); + static const DWORD enabled_planes = 0x3f; + struct wined3d_vec4 plane[6]; + unsigned int i, j;
TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n", iface, centers, radii, sphere_count, flags, return_values);
- return IDirect3DDevice7_ComputeSphereVisibility(&device->IDirect3DDevice7_iface, - centers, radii, sphere_count, flags, return_values); + prepare_clip_space_planes(impl_from_IDirect3DDevice3(iface), plane); + + compute_sphere_visibility(plane, enabled_planes, TRUE, centers, radii, sphere_count, return_values); + for (i = 0; i < sphere_count; ++i) + { + BOOL intersect_frustum = FALSE, outside_frustum = FALSE; + DWORD d3d7_result = return_values[i]; + + return_values[i] = 0; + + for (j = 0; j < 6; ++j) + { + DWORD clip = (d3d7_result >> j) & (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT); + + if (clip == D3DSTATUS_CLIPUNIONLEFT) + { + return_values[i] |= D3DVIS_INTERSECT_LEFT << j * 2; + intersect_frustum = TRUE; + } + else if (clip) + { + return_values[i] |= D3DVIS_OUTSIDE_LEFT << j * 2; + outside_frustum = TRUE; + } + } + if (outside_frustum) + return_values[i] |= D3DVIS_OUTSIDE_FRUSTUM; + else if (intersect_frustum) + return_values[i] |= D3DVIS_INTERSECT_FRUSTUM; + } + return D3D_OK; }
/*****************************************************************************