ddraw: Handle the Direct3D clipspace transformation.
Direct3D3 and earlier have an extra transformation to scale clipspace. It's controlled by the extra viewport parameters in those versions.
This commit is contained in:
parent
27e3e1a89b
commit
4a30db74b1
|
@ -300,6 +300,8 @@ struct IDirect3DDeviceImpl
|
|||
|
||||
/* Required to keep track which of two available texture blending modes in d3ddevice3 is used */
|
||||
BOOL legacyTextureBlending;
|
||||
D3DMATRIX legacy_projection;
|
||||
D3DMATRIX legacy_clipspace;
|
||||
|
||||
/* Light state */
|
||||
DWORD material;
|
||||
|
|
|
@ -3279,13 +3279,32 @@ IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
|
|||
}
|
||||
|
||||
static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
|
||||
D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
|
||||
D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
|
||||
{
|
||||
IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
|
||||
|
||||
TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
|
||||
TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
|
||||
|
||||
return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
|
||||
if (!matrix)
|
||||
return DDERR_INVALIDPARAMS;
|
||||
|
||||
if (state == D3DTRANSFORMSTATE_PROJECTION)
|
||||
{
|
||||
D3DMATRIX projection;
|
||||
HRESULT hr;
|
||||
|
||||
wined3d_mutex_lock();
|
||||
multiply_matrix(&projection, &This->legacy_clipspace, matrix);
|
||||
hr = wined3d_device_set_transform(This->wined3d_device,
|
||||
WINED3DTS_PROJECTION, (struct wined3d_matrix *)&projection);
|
||||
if (SUCCEEDED(hr))
|
||||
This->legacy_projection = *matrix;
|
||||
wined3d_mutex_unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, state, matrix);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
|
||||
|
@ -3370,13 +3389,24 @@ IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
|
|||
}
|
||||
|
||||
static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
|
||||
D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
|
||||
D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
|
||||
{
|
||||
IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
|
||||
|
||||
TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
|
||||
TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
|
||||
|
||||
return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
|
||||
if (!matrix)
|
||||
return DDERR_INVALIDPARAMS;
|
||||
|
||||
if (state == D3DTRANSFORMSTATE_PROJECTION)
|
||||
{
|
||||
wined3d_mutex_lock();
|
||||
*matrix = This->legacy_projection;
|
||||
wined3d_mutex_unlock();
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, state, matrix);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
|
||||
|
@ -3460,13 +3490,30 @@ IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
|
|||
}
|
||||
|
||||
static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
|
||||
D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
|
||||
D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
|
||||
{
|
||||
IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
|
||||
|
||||
TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
|
||||
TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
|
||||
|
||||
return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
|
||||
if (state == D3DTRANSFORMSTATE_PROJECTION)
|
||||
{
|
||||
D3DMATRIX projection, tmp;
|
||||
HRESULT hr;
|
||||
|
||||
wined3d_mutex_lock();
|
||||
multiply_matrix(&tmp, &This->legacy_projection, matrix);
|
||||
multiply_matrix(&projection, &This->legacy_clipspace, &tmp);
|
||||
hr = wined3d_device_set_transform(This->wined3d_device,
|
||||
WINED3DTS_PROJECTION, (struct wined3d_matrix *)&projection);
|
||||
if (SUCCEEDED(hr))
|
||||
This->legacy_projection = tmp;
|
||||
wined3d_mutex_unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, state, matrix);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
|
||||
|
@ -6911,6 +6958,13 @@ IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
|
|||
|
||||
HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
|
||||
{
|
||||
static const D3DMATRIX ident =
|
||||
{
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
HRESULT hr;
|
||||
|
||||
if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
|
||||
|
@ -6933,6 +6987,8 @@ HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDi
|
|||
}
|
||||
|
||||
device->legacyTextureBlending = FALSE;
|
||||
device->legacy_projection = ident;
|
||||
device->legacy_clipspace = ident;
|
||||
|
||||
/* Create an index buffer, it's needed for indexed drawing */
|
||||
hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
|
||||
|
|
|
@ -216,13 +216,13 @@ static void test_process_vertices(void)
|
|||
|
||||
hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
|
||||
ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
|
||||
todo_wine ok(compare_vec4(&dst_data[0], -6.500e+1f, +1.800e+2f, +2.000e-1f, +1.000e+0f, 4096),
|
||||
ok(compare_vec4(&dst_data[0], -6.500e+1f, +1.800e+2f, +2.000e-1f, +1.000e+0f, 4096),
|
||||
"Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
|
||||
dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
|
||||
todo_wine ok(compare_vec4(&dst_data[1], -4.000e+1f, +1.400e+2f, +4.000e-1f, +1.000e+0f, 4096),
|
||||
ok(compare_vec4(&dst_data[1], -4.000e+1f, +1.400e+2f, +4.000e-1f, +1.000e+0f, 4096),
|
||||
"Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
|
||||
dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
|
||||
todo_wine ok(compare_vec4(&dst_data[2], -1.500e+1f, +1.000e+2f, +6.000e-1f, +1.000e+0f, 4096),
|
||||
ok(compare_vec4(&dst_data[2], -1.500e+1f, +1.000e+2f, +6.000e-1f, +1.000e+0f, 4096),
|
||||
"Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
|
||||
dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
|
||||
hr = IDirect3DVertexBuffer_Unlock(dst_vb);
|
||||
|
@ -236,13 +236,13 @@ static void test_process_vertices(void)
|
|||
|
||||
hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
|
||||
ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
|
||||
todo_wine ok(compare_vec4(&dst_data[0], +8.500e+1f, -1.000e+2f, +1.800e+0f, +1.000e+0f, 4096),
|
||||
ok(compare_vec4(&dst_data[0], +8.500e+1f, -1.000e+2f, +1.800e+0f, +1.000e+0f, 4096),
|
||||
"Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
|
||||
dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
|
||||
todo_wine ok(compare_vec4(&dst_data[1], +1.100e+2f, -1.400e+2f, +2.000e+0f, +1.000e+0f, 4096),
|
||||
ok(compare_vec4(&dst_data[1], +1.100e+2f, -1.400e+2f, +2.000e+0f, +1.000e+0f, 4096),
|
||||
"Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
|
||||
dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
|
||||
todo_wine ok(compare_vec4(&dst_data[2], +1.350e+2f, -1.800e+2f, +2.200e+0f, +1.000e+0f, 4096),
|
||||
ok(compare_vec4(&dst_data[2], +1.350e+2f, -1.800e+2f, +2.200e+0f, +1.000e+0f, 4096),
|
||||
"Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
|
||||
dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
|
||||
hr = IDirect3DVertexBuffer_Unlock(dst_vb);
|
||||
|
@ -267,13 +267,13 @@ static void test_process_vertices(void)
|
|||
|
||||
hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
|
||||
ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
|
||||
todo_wine ok(compare_vec4(&dst_data[0], +7.500e+1f, +4.000e+1f, -8.000e-1f, +1.000e+0f, 4096),
|
||||
ok(compare_vec4(&dst_data[0], +7.500e+1f, +4.000e+1f, -8.000e-1f, +1.000e+0f, 4096),
|
||||
"Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
|
||||
dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
|
||||
todo_wine ok(compare_vec4(&dst_data[1], +1.200e+2f, +2.000e+1f, -1.000e+0f, +1.000e+0f, 4096),
|
||||
ok(compare_vec4(&dst_data[1], +1.200e+2f, +2.000e+1f, -1.000e+0f, +1.000e+0f, 4096),
|
||||
"Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
|
||||
dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
|
||||
todo_wine ok(compare_vec4(&dst_data[2], +1.650e+2f, +0.000e+0f, -1.200e+0f, +1.000e+0f, 4096),
|
||||
ok(compare_vec4(&dst_data[2], +1.650e+2f, +0.000e+0f, -1.200e+0f, +1.000e+0f, 4096),
|
||||
"Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
|
||||
dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
|
||||
hr = IDirect3DVertexBuffer_Unlock(dst_vb);
|
||||
|
@ -298,13 +298,13 @@ static void test_process_vertices(void)
|
|||
|
||||
hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
|
||||
ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
|
||||
todo_wine ok(compare_vec4(&dst_data[0], +1.100e+2f, +6.800e+1f, +7.000e+0f, +1.000e+0f, 4096),
|
||||
ok(compare_vec4(&dst_data[0], +1.100e+2f, +6.800e+1f, +7.000e+0f, +1.000e+0f, 4096),
|
||||
"Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
|
||||
dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
|
||||
todo_wine ok(compare_vec4(&dst_data[1], +1.170e+2f, +6.600e+1f, +8.000e+0f, +1.000e+0f, 4096),
|
||||
ok(compare_vec4(&dst_data[1], +1.170e+2f, +6.600e+1f, +8.000e+0f, +1.000e+0f, 4096),
|
||||
"Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
|
||||
dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
|
||||
todo_wine ok(compare_vec4(&dst_data[2], +1.240e+2f, +6.400e+1f, +9.000e+0f, +1.000e+0f, 4096),
|
||||
ok(compare_vec4(&dst_data[2], +1.240e+2f, +6.400e+1f, +9.000e+0f, +1.000e+0f, 4096),
|
||||
"Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
|
||||
dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
|
||||
hr = IDirect3DVertexBuffer_Unlock(dst_vb);
|
||||
|
|
|
@ -30,6 +30,26 @@ WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
|
|||
* Helper functions
|
||||
*****************************************************************************/
|
||||
|
||||
static void update_clip_space(IDirect3DDeviceImpl *device,
|
||||
struct wined3d_vec3 *scale, struct wined3d_vec3 *offset)
|
||||
{
|
||||
D3DMATRIX clip_space =
|
||||
{
|
||||
scale->x, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, scale->y, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, scale->z, 0.0f,
|
||||
offset->x, offset->y, offset->z, 1.0f,
|
||||
};
|
||||
D3DMATRIX projection;
|
||||
HRESULT hr;
|
||||
|
||||
multiply_matrix(&projection, &clip_space, &device->legacy_projection);
|
||||
hr = wined3d_device_set_transform(device->wined3d_device,
|
||||
WINED3DTS_PROJECTION, (struct wined3d_matrix *)&projection);
|
||||
if (SUCCEEDED(hr))
|
||||
device->legacy_clipspace = clip_space;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* viewport_activate
|
||||
*
|
||||
|
@ -38,6 +58,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
|
|||
*****************************************************************************/
|
||||
void viewport_activate(IDirect3DViewportImpl *This, BOOL ignore_lights)
|
||||
{
|
||||
struct wined3d_vec3 scale, offset;
|
||||
D3DVIEWPORT7 vp;
|
||||
|
||||
if (!ignore_lights)
|
||||
|
@ -58,8 +79,15 @@ void viewport_activate(IDirect3DViewportImpl *This, BOOL ignore_lights)
|
|||
vp.dwY = This->viewports.vp2.dwY;
|
||||
vp.dwHeight = This->viewports.vp2.dwHeight;
|
||||
vp.dwWidth = This->viewports.vp2.dwWidth;
|
||||
vp.dvMinZ = This->viewports.vp2.dvMinZ;
|
||||
vp.dvMaxZ = This->viewports.vp2.dvMaxZ;
|
||||
vp.dvMinZ = 0.0f;
|
||||
vp.dvMaxZ = 1.0f;
|
||||
|
||||
scale.x = 2.0f / This->viewports.vp2.dvClipWidth;
|
||||
scale.y = 2.0f / This->viewports.vp2.dvClipHeight;
|
||||
scale.z = 1.0f / (This->viewports.vp2.dvMaxZ - This->viewports.vp2.dvMinZ);
|
||||
offset.x = -2.0f * This->viewports.vp2.dvClipX / This->viewports.vp2.dvClipWidth - 1.0f;
|
||||
offset.y = -2.0f * This->viewports.vp2.dvClipY / This->viewports.vp2.dvClipHeight + 1.0f;
|
||||
offset.z = -This->viewports.vp2.dvMinZ / (This->viewports.vp2.dvMaxZ - This->viewports.vp2.dvMinZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -67,11 +95,18 @@ void viewport_activate(IDirect3DViewportImpl *This, BOOL ignore_lights)
|
|||
vp.dwY = This->viewports.vp1.dwY;
|
||||
vp.dwHeight = This->viewports.vp1.dwHeight;
|
||||
vp.dwWidth = This->viewports.vp1.dwWidth;
|
||||
vp.dvMinZ = This->viewports.vp1.dvMinZ;
|
||||
vp.dvMaxZ = This->viewports.vp1.dvMaxZ;
|
||||
vp.dvMinZ = 0.0f;
|
||||
vp.dvMaxZ = 1.0f;
|
||||
|
||||
scale.x = 2.0f * This->viewports.vp1.dvScaleX / This->viewports.vp1.dwWidth;
|
||||
scale.y = 2.0f * This->viewports.vp1.dvScaleY / This->viewports.vp1.dwHeight;
|
||||
scale.z = 1.0f;
|
||||
offset.x = 0.0f;
|
||||
offset.y = 0.0f;
|
||||
offset.z = 0.0f;
|
||||
}
|
||||
|
||||
/* And also set the viewport */
|
||||
update_clip_space(This->active_device, &scale, &offset);
|
||||
IDirect3DDevice7_SetViewport(&This->active_device->IDirect3DDevice7_iface, &vp);
|
||||
}
|
||||
|
||||
|
@ -368,7 +403,7 @@ IDirect3DViewportImpl_TransformVertices(IDirect3DViewport3 *iface,
|
|||
DWORD *lpOffScreen)
|
||||
{
|
||||
IDirect3DViewportImpl *This = impl_from_IDirect3DViewport3(iface);
|
||||
D3DMATRIX view_mat, world_mat, proj_mat, mat;
|
||||
D3DMATRIX view_mat, world_mat, mat;
|
||||
float *in;
|
||||
float *out;
|
||||
float x, y, z, w;
|
||||
|
@ -398,12 +433,10 @@ IDirect3DViewportImpl_TransformVertices(IDirect3DViewport3 *iface,
|
|||
wined3d_mutex_lock();
|
||||
wined3d_device_get_transform(This->active_device->wined3d_device,
|
||||
D3DTRANSFORMSTATE_VIEW, (struct wined3d_matrix *)&view_mat);
|
||||
wined3d_device_get_transform(This->active_device->wined3d_device,
|
||||
D3DTRANSFORMSTATE_PROJECTION, (struct wined3d_matrix *)&proj_mat);
|
||||
wined3d_device_get_transform(This->active_device->wined3d_device,
|
||||
WINED3DTS_WORLDMATRIX(0), (struct wined3d_matrix *)&world_mat);
|
||||
multiply_matrix(&mat,&view_mat,&world_mat);
|
||||
multiply_matrix(&mat,&proj_mat,&mat);
|
||||
multiply_matrix(&mat, &view_mat, &world_mat);
|
||||
multiply_matrix(&mat, &This->active_device->legacy_projection, &mat);
|
||||
|
||||
in = lpData->lpIn;
|
||||
out = lpData->lpOut;
|
||||
|
|
Loading…
Reference in New Issue