ddraw: Fix handling of alpha with D3DTBLEND_MODULATE.
This commit is contained in:
parent
536f98000d
commit
6810ebb4c1
|
@ -28,7 +28,6 @@
|
|||
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -36,6 +35,7 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#define COBJMACROS
|
||||
#define NONAMELESSUNION
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
|
@ -47,6 +47,7 @@
|
|||
#include "d3d.h"
|
||||
|
||||
#include "ddraw_private.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(d3d7);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(ddraw_thunk);
|
||||
|
@ -2369,15 +2370,93 @@ Thunk_IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
|
|||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
|
||||
IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
|
||||
D3DRENDERSTATETYPE dwRenderStateType,
|
||||
DWORD *lpdwRenderState)
|
||||
{
|
||||
ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
|
||||
TRACE_(ddraw_thunk)("(%p)->(%08x,%p) thunking to IDirect3DDevice7 interface.\n", This, dwRenderStateType, lpdwRenderState);
|
||||
return IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
|
||||
TRACE("(%p)->(%08x,%p): Relay\n", This, dwRenderStateType, lpdwRenderState);
|
||||
|
||||
/* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
|
||||
the mapping to get the value; other states relayed to IDirect3DDevice7::GetRenderState */
|
||||
switch(dwRenderStateType)
|
||||
{
|
||||
case D3DRENDERSTATE_TEXTUREMAPBLEND:
|
||||
{
|
||||
DWORD colorop, colorarg1, colorarg2;
|
||||
DWORD alphaop, alphaarg1, alphaarg2;
|
||||
|
||||
EnterCriticalSection(&ddraw_cs);
|
||||
|
||||
IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
|
||||
IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
|
||||
IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
|
||||
IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
|
||||
IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
|
||||
IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
|
||||
|
||||
if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
|
||||
alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
|
||||
{
|
||||
*lpdwRenderState = D3DTBLEND_DECAL;
|
||||
}
|
||||
else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
|
||||
alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
|
||||
{
|
||||
*lpdwRenderState = D3DTBLEND_DECALALPHA;
|
||||
}
|
||||
else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
|
||||
alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
|
||||
{
|
||||
*lpdwRenderState = D3DTBLEND_MODULATEALPHA;
|
||||
}
|
||||
else
|
||||
{
|
||||
HRESULT hr;
|
||||
BOOL tex_alpha = FALSE;
|
||||
IWineD3DBaseTexture *tex = NULL;
|
||||
WINED3DSURFACE_DESC desc;
|
||||
WINED3DFORMAT fmt;
|
||||
DDPIXELFORMAT ddfmt;
|
||||
|
||||
hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
|
||||
0,
|
||||
&tex);
|
||||
|
||||
if(hr == WINED3D_OK && tex)
|
||||
{
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.Format = &fmt;
|
||||
hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ddfmt.dwSize = sizeof(ddfmt);
|
||||
PixelFormat_WineD3DtoDD(&ddfmt, fmt);
|
||||
if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
|
||||
}
|
||||
|
||||
IWineD3DBaseTexture_Release(tex);
|
||||
}
|
||||
|
||||
if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
|
||||
alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == (tex_alpha ? WINED3DTA_TEXTURE : WINED3DTA_CURRENT)))
|
||||
{
|
||||
ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
|
||||
}
|
||||
|
||||
*lpdwRenderState = D3DTBLEND_MODULATE;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&ddraw_cs);
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
default:
|
||||
return IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
|
||||
dwRenderStateType,
|
||||
lpdwRenderState);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -2525,20 +2604,101 @@ IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
|
|||
Value);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
|
||||
|
||||
hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
|
||||
RenderStateType,
|
||||
Value);
|
||||
break;
|
||||
}
|
||||
LeaveCriticalSection(&ddraw_cs);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
Thunk_IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
|
||||
D3DRENDERSTATETYPE RenderStateType,
|
||||
DWORD Value)
|
||||
{
|
||||
ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
|
||||
TRACE_(ddraw_thunk)("(%p)->(%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, RenderStateType, Value);
|
||||
return IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
|
||||
RenderStateType,
|
||||
Value);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
|
||||
D3DRENDERSTATETYPE RenderStateType,
|
||||
DWORD Value)
|
||||
{
|
||||
/* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
|
||||
for this state can be directly mapped to texture stage colorop and alphaop, but
|
||||
D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
|
||||
from diffuse otherwise. So changing the texture is monitored here to modify
|
||||
alphaarg when needed.
|
||||
|
||||
Other states are relayed to IDirect3DDevice7
|
||||
|
||||
Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation */
|
||||
|
||||
HRESULT hr;
|
||||
ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
|
||||
TRACE("(%p)->(%08x,%d): Relay\n", This, RenderStateType, Value);
|
||||
|
||||
switch(RenderStateType)
|
||||
{
|
||||
case D3DRENDERSTATE_TEXTUREMAPBLEND:
|
||||
{
|
||||
/* Old texture combine setup style, superseded by texture stage states
|
||||
* in D3D7. It is safe for us to wrap it to texture stage states.
|
||||
*/
|
||||
EnterCriticalSection(&ddraw_cs);
|
||||
|
||||
switch ( (D3DTEXTUREBLEND) Value)
|
||||
{
|
||||
case D3DTBLEND_MODULATE:
|
||||
{
|
||||
BOOL tex_alpha = FALSE;
|
||||
IWineD3DBaseTexture *tex = NULL;
|
||||
WINED3DSURFACE_DESC desc;
|
||||
WINED3DFORMAT fmt;
|
||||
DDPIXELFORMAT ddfmt;
|
||||
|
||||
hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
|
||||
0,
|
||||
&tex);
|
||||
|
||||
if(hr == WINED3D_OK && tex)
|
||||
{
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.Format = &fmt;
|
||||
hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ddfmt.dwSize = sizeof(ddfmt);
|
||||
PixelFormat_WineD3DtoDD(&ddfmt, fmt);
|
||||
if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
|
||||
}
|
||||
|
||||
IWineD3DBaseTexture_Release(tex);
|
||||
}
|
||||
|
||||
IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
|
||||
if (tex_alpha)
|
||||
{
|
||||
IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_CURRENT);
|
||||
}
|
||||
|
||||
IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
|
||||
IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
|
||||
IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
|
||||
IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
|
||||
IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case D3DTBLEND_MODULATEALPHA:
|
||||
IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
|
||||
|
@ -2566,48 +2726,79 @@ IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
|
|||
|
||||
default:
|
||||
ERR("Unhandled texture environment %d !\n",Value);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&ddraw_cs);
|
||||
|
||||
hr = D3D_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
case D3DRENDERSTATE_TEXTUREHANDLE:
|
||||
{
|
||||
DWORD texmapblend;
|
||||
|
||||
IDirect3DDevice2_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
|
||||
|
||||
hr = IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
|
||||
D3DRENDERSTATE_TEXTUREHANDLE,
|
||||
Value);
|
||||
|
||||
if (texmapblend == D3DTBLEND_MODULATE)
|
||||
{
|
||||
BOOL tex_alpha = FALSE;
|
||||
IWineD3DBaseTexture *tex = NULL;
|
||||
WINED3DSURFACE_DESC desc;
|
||||
WINED3DFORMAT fmt;
|
||||
DDPIXELFORMAT ddfmt;
|
||||
|
||||
EnterCriticalSection(&ddraw_cs);
|
||||
|
||||
hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
|
||||
0,
|
||||
&tex);
|
||||
|
||||
if(hr == WINED3D_OK && tex)
|
||||
{
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.Format = &fmt;
|
||||
hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ddfmt.dwSize = sizeof(ddfmt);
|
||||
PixelFormat_WineD3DtoDD(&ddfmt, fmt);
|
||||
if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
|
||||
}
|
||||
|
||||
IWineD3DBaseTexture_Release(tex);
|
||||
}
|
||||
hr = D3D_OK;
|
||||
|
||||
/* alphaop is WINED3DTOP_SELECTARG1 if it's D3DTBLEND_MODULATE, so only modify alphaarg1 */
|
||||
if (tex_alpha)
|
||||
{
|
||||
IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_CURRENT);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&ddraw_cs);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
/* FIXME: Unhandled: D3DRENDERSTATE_STIPPLEPATTERN00 - 31 */
|
||||
|
||||
hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
|
||||
RenderStateType,
|
||||
Value);
|
||||
hr = IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
|
||||
RenderStateType,
|
||||
Value);
|
||||
break;
|
||||
}
|
||||
LeaveCriticalSection(&ddraw_cs);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
Thunk_IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
|
||||
D3DRENDERSTATETYPE RenderStateType,
|
||||
DWORD Value)
|
||||
{
|
||||
ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
|
||||
TRACE_(ddraw_thunk)("(%p)->(%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, RenderStateType, Value);
|
||||
return IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
|
||||
RenderStateType,
|
||||
Value);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
Thunk_IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
|
||||
D3DRENDERSTATETYPE RenderStateType,
|
||||
DWORD Value)
|
||||
{
|
||||
ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
|
||||
TRACE_(ddraw_thunk)("(%p)->(%08x,%08x) thunking to IDirect3DDevice7 interface.\n", This, RenderStateType, Value);
|
||||
return IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
|
||||
RenderStateType,
|
||||
Value);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Direct3DDevice3::SetLightState
|
||||
*
|
||||
|
@ -5441,8 +5632,8 @@ const IDirect3DDevice2Vtbl IDirect3DDevice2_Vtbl =
|
|||
Thunk_IDirect3DDeviceImpl_2_Vertex,
|
||||
Thunk_IDirect3DDeviceImpl_2_Index,
|
||||
Thunk_IDirect3DDeviceImpl_2_End,
|
||||
Thunk_IDirect3DDeviceImpl_2_GetRenderState,
|
||||
Thunk_IDirect3DDeviceImpl_2_SetRenderState,
|
||||
IDirect3DDeviceImpl_2_GetRenderState,
|
||||
IDirect3DDeviceImpl_2_SetRenderState,
|
||||
Thunk_IDirect3DDeviceImpl_2_GetLightState,
|
||||
Thunk_IDirect3DDeviceImpl_2_SetLightState,
|
||||
Thunk_IDirect3DDeviceImpl_2_SetTransform,
|
||||
|
|
|
@ -317,7 +317,7 @@ IDirect3DExecuteBufferImpl_Execute(IDirect3DExecuteBufferImpl *This,
|
|||
for (i = 0; i < count; i++) {
|
||||
LPD3DSTATE ci = (LPD3DSTATE) instr;
|
||||
|
||||
IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(lpDevice, IDirect3DDevice7),
|
||||
IDirect3DDevice2_SetRenderState(ICOM_INTERFACE(lpDevice, IDirect3DDevice2),
|
||||
ci->u1.drstRenderStateType, ci->u2.dwArg[0]);
|
||||
|
||||
instr += size;
|
||||
|
|
Loading…
Reference in New Issue