Commit f700cbe7 authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

wined3d: Add an alpha blending test.

parent f29d947f
......@@ -729,6 +729,187 @@ out:
}
}
static void alpha_test(IDirect3DDevice8 *device)
{
HRESULT hr;
IDirect3DTexture8 *offscreenTexture;
IDirect3DSurface8 *backbuffer = NULL, *offscreen = NULL, *depthstencil = NULL;
DWORD color, red, green, blue;
struct vertex quad1[] =
{
{-1.0f, -1.0f, 0.1f, 0x4000ff00},
{-1.0f, 0.0f, 0.1f, 0x4000ff00},
{ 1.0f, -1.0f, 0.1f, 0x4000ff00},
{ 1.0f, 0.0f, 0.1f, 0x4000ff00},
};
struct vertex quad2[] =
{
{-1.0f, 0.0f, 0.1f, 0xc00000ff},
{-1.0f, 1.0f, 0.1f, 0xc00000ff},
{ 1.0f, 0.0f, 0.1f, 0xc00000ff},
{ 1.0f, 1.0f, 0.1f, 0xc00000ff},
};
static const float composite_quad[][5] = {
{ 0.0f, -1.0f, 0.1f, 0.0f, 1.0f},
{ 0.0f, 1.0f, 0.1f, 0.0f, 0.0f},
{ 1.0f, -1.0f, 0.1f, 1.0f, 1.0f},
{ 1.0f, 1.0f, 0.1f, 1.0f, 0.0f},
};
/* Clear the render target with alpha = 0.5 */
hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture);
ok(hr == D3D_OK || D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr);
hr = IDirect3DDevice8_GetDepthStencilSurface(device, &depthstencil);
ok(hr == D3D_OK, "IDirect3DDevice8_GetDepthStencilSurface failed, hr = %#08x\n", hr);
hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
ok(hr == D3D_OK, "Can't get back buffer, hr = %#08x\n", hr);
if(!backbuffer) {
goto out;
}
hr = IDirect3DTexture8_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
ok(hr == D3D_OK, "Can't get offscreen surface, hr = %#08x\n", hr);
if(!offscreen) {
goto out;
}
hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
ok(hr == D3D_OK, "SetVertexShader failed, hr = %#08x\n", hr);
hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
ok(hr == D3D_OK, "SetTextureStageState failed, hr = %#08x\n", hr);
hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
ok(hr == D3D_OK, "SetTextureStageState failed, hr = %#08x\n", hr);
hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MINFILTER, D3DTEXF_NONE);
ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MINFILTER failed (%#08x)\n", hr);
hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, D3DTEXF_NONE);
ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MAGFILTER failed (%#08x)\n", hr);
hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %s\n", DXGetErrorString8(hr));
hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
if(IDirect3DDevice8_BeginScene(device) == D3D_OK) {
/* Draw two quads, one with src alpha blending, one with dest alpha blending. The
* SRCALPHA / INVSRCALPHA blend doesn't give any surprises. Colors are blended based on
* the input alpha
*
* The DESTALPHA / INVDESTALPHA do not "work" on the regular buffer because there is no alpha.
* They give essentially ZERO and ONE blend factors
*/
hr = IDirect3DDevice8_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice8_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
hr = IDirect3DDevice8_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice8_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
/* Switch to the offscreen buffer, and redo the testing. SRCALPHA and DESTALPHA. The offscreen buffer
* has a alpha channel on its own. Clear the offscreen buffer with alpha = 0.5 again, then draw the
* quads again. The SRCALPHA/INVSRCALPHA doesn't give any surprises, but the DESTALPHA/INVDESTALPHA
* blending works as supposed now - blend factor is 0.5 in both cases, not 0.75 as from the input
* vertices
*/
hr = IDirect3DDevice8_SetRenderTarget(device, offscreen, 0);
ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
hr = IDirect3DDevice8_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice8_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
hr = IDirect3DDevice8_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice8_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depthstencil);
ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
/* Render the offscreen texture onto the frame buffer to be able to compare it regularly.
* Disable alpha blending for the final composition
*/
hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_TEX1);
ok(hr == D3D_OK, "SetVertexShader failed, hr = %#08x\n", hr);
hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *) offscreenTexture);
ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture failed, hr = %08x\n", hr);
hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, composite_quad, sizeof(float) * 5);
ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture failed, hr = %08x\n", hr);
hr = IDirect3DDevice8_EndScene(device);
ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed, hr = %08x\n", hr);
}
IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
color = getPixelColor(device, 160, 360);
red = (color & 0x00ff0000) >> 16;
green = (color & 0x0000ff00) >> 8;
blue = (color & 0x000000ff);
ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00,
"SRCALPHA on frame buffer returned color %08x, expected 0x00bf4000\n", color);
color = getPixelColor(device, 160, 120);
red = (color & 0x00ff0000) >> 16;
green = (color & 0x0000ff00) >> 8;
blue = (color & 0x000000ff);
ok(red == 0x00 && green == 0x00 && blue >= 0xfe && blue <= 0xff ,
"DSTALPHA on frame buffer returned color %08x, expected 0x00ff0000\n", color);
color = getPixelColor(device, 480, 360);
red = (color & 0x00ff0000) >> 16;
green = (color & 0x0000ff00) >> 8;
blue = (color & 0x000000ff);
ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00,
"SRCALPHA on texture returned color %08x, expected bar\n", color);
color = getPixelColor(device, 480, 120);
red = (color & 0x00ff0000) >> 16;
green = (color & 0x0000ff00) >> 8;
blue = (color & 0x000000ff);
ok(red >= 0x7e && red <= 0x81 && green == 0x00 && blue >= 0x7e && blue <= 0x81,
"DSTALPHA on texture returned color %08x, expected foo\n", color);
out:
/* restore things */
if(backbuffer) {
IDirect3DSurface8_Release(backbuffer);
}
if(offscreenTexture) {
IDirect3DTexture8_Release(offscreenTexture);
}
if(offscreen) {
IDirect3DSurface8_Release(offscreen);
}
if(depthstencil) {
IDirect3DSurface8_Release(depthstencil);
}
}
START_TEST(visual)
{
IDirect3DDevice8 *device_ptr;
......@@ -789,6 +970,7 @@ START_TEST(visual)
fog_test(device_ptr);
present_test(device_ptr);
offscreen_test(device_ptr);
alpha_test(device_ptr);
if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1))
{
......
......@@ -5172,6 +5172,182 @@ static void fog_srgbwrite_test(IDirect3DDevice9 *device)
"Fog with D3DRS_SRGBWRITEENABLE returned color 0x%08x, expected 0x00808080\n", color);
}
static void alpha_test(IDirect3DDevice9 *device)
{
HRESULT hr;
IDirect3DTexture9 *offscreenTexture;
IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
DWORD color, red, green, blue;
struct vertex quad1[] =
{
{-1.0f, -1.0f, 0.1f, 0x4000ff00},
{-1.0f, 0.0f, 0.1f, 0x4000ff00},
{ 1.0f, -1.0f, 0.1f, 0x4000ff00},
{ 1.0f, 0.0f, 0.1f, 0x4000ff00},
};
struct vertex quad2[] =
{
{-1.0f, 0.0f, 0.1f, 0xc00000ff},
{-1.0f, 1.0f, 0.1f, 0xc00000ff},
{ 1.0f, 0.0f, 0.1f, 0xc00000ff},
{ 1.0f, 1.0f, 0.1f, 0xc00000ff},
};
static const float composite_quad[][5] = {
{ 0.0f, -1.0f, 0.1f, 0.0f, 1.0f},
{ 0.0f, 1.0f, 0.1f, 0.0f, 0.0f},
{ 1.0f, -1.0f, 0.1f, 1.0f, 1.0f},
{ 1.0f, 1.0f, 0.1f, 1.0f, 0.0f},
};
/* Clear the render target with alpha = 0.5 */
hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
ok(hr == D3D_OK || D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr);
hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
ok(hr == D3D_OK, "Can't get back buffer, hr = %s\n", DXGetErrorString9(hr));
if(!backbuffer) {
goto out;
}
hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
ok(hr == D3D_OK, "Can't get offscreen surface, hr = %s\n", DXGetErrorString9(hr));
if(!offscreen) {
goto out;
}
hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %#08x\n", hr);
hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_NONE);
ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_NONE);
ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
/* Draw two quads, one with src alpha blending, one with dest alpha blending. The
* SRCALPHA / INVSRCALPHA blend doesn't give any surprises. Colors are blended based on
* the input alpha
*
* The DESTALPHA / INVDESTALPHA do not "work" on the regular buffer because there is no alpha.
* They give essentially ZERO and ONE blend factors
*/
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
/* Switch to the offscreen buffer, and redo the testing. SRCALPHA and DESTALPHA. The offscreen buffer
* has a alpha channel on its own. Clear the offscreen buffer with alpha = 0.5 again, then draw the
* quads again. The SRCALPHA/INVSRCALPHA doesn't give any surprises, but the DESTALPHA/INVDESTALPHA
* blending works as supposed now - blend factor is 0.5 in both cases, not 0.75 as from the input
* vertices
*/
hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
/* Render the offscreen texture onto the frame buffer to be able to compare it regularly.
* Disable alpha blending for the final composition
*/
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %#08x\n", hr);
hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr = %08x\n", hr);
hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, composite_quad, sizeof(float) * 5);
ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr = %08x\n", hr);
hr = IDirect3DDevice9_EndScene(device);
ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed, hr = %08x\n", hr);
}
IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
color = getPixelColor(device, 160, 360);
red = (color & 0x00ff0000) >> 16;
green = (color & 0x0000ff00) >> 8;
blue = (color & 0x000000ff);
ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00,
"SRCALPHA on frame buffer returned color %08x, expected 0x00bf4000\n", color);
color = getPixelColor(device, 160, 120);
red = (color & 0x00ff0000) >> 16;
green = (color & 0x0000ff00) >> 8;
blue = (color & 0x000000ff);
ok(red == 0x00 && green == 0x00 && blue >= 0xfe && blue <= 0xff ,
"DSTALPHA on frame buffer returned color %08x, expected 0x00ff0000\n", color);
color = getPixelColor(device, 480, 360);
red = (color & 0x00ff0000) >> 16;
green = (color & 0x0000ff00) >> 8;
blue = (color & 0x000000ff);
ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00,
"SRCALPHA on texture returned color %08x, expected bar\n", color);
color = getPixelColor(device, 480, 120);
red = (color & 0x00ff0000) >> 16;
green = (color & 0x0000ff00) >> 8;
blue = (color & 0x000000ff);
ok(red >= 0x7e && red <= 0x81 && green == 0x00 && blue >= 0x7e && blue <= 0x81,
"DSTALPHA on texture returned color %08x, expected foo\n", color);
out:
/* restore things */
if(backbuffer) {
IDirect3DSurface9_Release(backbuffer);
}
if(offscreenTexture) {
IDirect3DTexture9_Release(offscreenTexture);
}
if(offscreen) {
IDirect3DSurface9_Release(offscreen);
}
}
START_TEST(visual)
{
IDirect3DDevice9 *device_ptr;
......@@ -5246,6 +5422,7 @@ START_TEST(visual)
skip("No mipmap support\n");
}
offscreen_test(device_ptr);
alpha_test(device_ptr);
release_buffer_test(device_ptr);
float_texture_test(device_ptr);
texture_transform_flags_test(device_ptr);
......
......@@ -594,6 +594,173 @@ out:
}
}
static void alpha_test(IDirect3DDevice7 *device)
{
HRESULT hr;
IDirectDrawSurface7 *backbuffer = NULL, *offscreen = NULL;
DWORD color, red, green, blue;
DDSURFACEDESC2 ddsd;
struct vertex quad1[] =
{
{-1.0f, -1.0f, 0.1f, 0x4000ff00},
{-1.0f, 0.0f, 0.1f, 0x4000ff00},
{ 1.0f, -1.0f, 0.1f, 0x4000ff00},
{ 1.0f, 0.0f, 0.1f, 0x4000ff00},
};
struct vertex quad2[] =
{
{-1.0f, 0.0f, 0.1f, 0xc00000ff},
{-1.0f, 1.0f, 0.1f, 0xc00000ff},
{ 1.0f, 0.0f, 0.1f, 0xc00000ff},
{ 1.0f, 1.0f, 0.1f, 0xc00000ff},
};
static const float composite_quad[][5] = {
{ 0.0f, -1.0f, 0.1f, 0.0f, 1.0f},
{ 0.0f, 1.0f, 0.1f, 0.0f, 0.0f},
{ 1.0f, -1.0f, 0.1f, 1.0f, 1.0f},
{ 1.0f, 1.0f, 0.1f, 1.0f, 0.0f},
};
/* Clear the render target with alpha = 0.5 */
hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
ddsd.dwWidth = 128;
ddsd.dwHeight = 128;
ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
U4(ddsd).ddpfPixelFormat.dwRGBBitCount = 32;
U4(ddsd).ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
U4(ddsd).ddpfPixelFormat.dwRBitMask = 0x00ff0000;
U4(ddsd).ddpfPixelFormat.dwGBitMask = 0x0000ff00;
U4(ddsd).ddpfPixelFormat.dwBBitMask = 0x000000ff;
hr = IDirectDraw7_CreateSurface(DirectDraw, &ddsd, &offscreen, NULL);
ok(hr == D3D_OK, "Creating the offscreen render target failed, hr = %08x\n", hr);
if(!offscreen) {
goto out;
}
hr = IDirect3DDevice7_GetRenderTarget(device, &backbuffer);
ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
if(!backbuffer) {
goto out;
}
hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_MINFILTER, D3DFILTER_NEAREST);
ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, D3DFILTER_NEAREST);
ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
if(IDirect3DDevice7_BeginScene(device) == D3D_OK) {
/* Draw two quads, one with src alpha blending, one with dest alpha blending. The
* SRCALPHA / INVSRCALPHA blend doesn't give any surprises. Colors are blended based on
* the input alpha
*
* The DESTALPHA / INVDESTALPHA do not "work" on the regular buffer because there is no alpha.
* They give essentially ZERO and ONE blend factors
*/
hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad1, 4, 0);
ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_DESTALPHA);
ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVDESTALPHA);
ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad2, 4, 0);
ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
/* Switch to the offscreen buffer, and redo the testing. SRCALPHA and DESTALPHA. The offscreen buffer
* has a alpha channel on its own. Clear the offscreen buffer with alpha = 0.5 again, then draw the
* quads again. The SRCALPHA/INVSRCALPHA doesn't give any surprises, but the DESTALPHA/INVDESTALPHA
* blending works as supposed now - blend factor is 0.5 in both cases, not 0.75 as from the input
* vertices
*/
hr = IDirect3DDevice7_SetRenderTarget(device, offscreen, 0);
ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad1, 4, 0);
ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_DESTALPHA);
ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVDESTALPHA);
ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad2, 4, 0);
ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_SetRenderTarget(device, backbuffer, 0);
ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
/* Render the offscreen texture onto the frame buffer to be able to compare it regularly.
* Disable alpha blending for the final composition
*/
hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_SetTexture(device, 0, offscreen);
ok(hr == D3D_OK, "IDirect3DDevice7_SetTexture failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, composite_quad, 4, 0);
ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_SetTexture(device, 0, NULL);
ok(hr == D3D_OK, "IDirect3DDevice7_SetTexture failed, hr = %08x\n", hr);
hr = IDirect3DDevice7_EndScene(device);
ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed, hr = %08x\n", hr);
}
color = getPixelColor(device, 160, 360);
red = (color & 0x00ff0000) >> 16;
green = (color & 0x0000ff00) >> 8;
blue = (color & 0x000000ff);
ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00,
"SRCALPHA on frame buffer returned color %08x, expected 0x00bf4000\n", color);
color = getPixelColor(device, 160, 120);
red = (color & 0x00ff0000) >> 16;
green = (color & 0x0000ff00) >> 8;
blue = (color & 0x000000ff);
ok(red == 0x00 && green == 0x00 && blue >= 0xfe && blue <= 0xff ,
"DSTALPHA on frame buffer returned color %08x, expected 0x00ff0000\n", color);
color = getPixelColor(device, 480, 360);
red = (color & 0x00ff0000) >> 16;
green = (color & 0x0000ff00) >> 8;
blue = (color & 0x000000ff);
ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00,
"SRCALPHA on texture returned color %08x, expected bar\n", color);
color = getPixelColor(device, 480, 120);
red = (color & 0x00ff0000) >> 16;
green = (color & 0x0000ff00) >> 8;
blue = (color & 0x000000ff);
ok(red >= 0x7e && red <= 0x81 && green == 0x00 && blue >= 0x7e && blue <= 0x81,
"DSTALPHA on texture returned color %08x, expected foo\n", color);
out:
if(offscreen) IDirectDrawSurface7_Release(offscreen);
if(backbuffer) IDirectDrawSurface7_Release(backbuffer);
}
START_TEST(visual)
{
HRESULT hr;
......@@ -638,6 +805,7 @@ START_TEST(visual)
clear_test(Direct3DDevice);
fog_test(Direct3DDevice);
offscreen_test(Direct3DDevice);
alpha_test(Direct3DDevice);
cleanup:
releaseObjects();
......
......@@ -682,6 +682,20 @@ static inline WineD3DContext *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurf
BOOL readTexture = wined3d_settings.offscreen_rendering_mode != ORM_FBO && This->render_offscreen;
WineD3DContext *context = This->activeContext;
BOOL oldRenderOffscreen = This->render_offscreen;
const WINED3DFORMAT oldFmt = ((IWineD3DSurfaceImpl *) This->lastActiveRenderTarget)->resource.format;
const WINED3DFORMAT newFmt = ((IWineD3DSurfaceImpl *) target)->resource.format;
/* To compensate the lack of format switching with some offscreen rendering methods and on onscreen buffers
* the alpha blend state changes with different render target formats
*/
if(oldFmt != newFmt) {
const StaticPixelFormatDesc *old = getFormatDescEntry(oldFmt, NULL, NULL);
const StaticPixelFormatDesc *new = getFormatDescEntry(oldFmt, NULL, NULL);
if((old->alphaMask && !new->alphaMask) || (!old->alphaMask && new->alphaMask)) {
Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE));
}
}
hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **) &swapchain);
if(hr == WINED3D_OK && swapchain) {
......
......@@ -234,6 +234,8 @@ static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD
static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
int srcBlend = GL_ZERO;
int dstBlend = GL_ZERO;
const StaticPixelFormatDesc *rtFormat;
IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
/* GL_LINE_SMOOTH needs GL_BLEND to work, according to the red book, and special blending params */
if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE] ||
......@@ -255,11 +257,23 @@ static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break;
case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break;
case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break;
case WINED3DBLEND_DESTALPHA : dstBlend = GL_DST_ALPHA; break;
case WINED3DBLEND_INVDESTALPHA : dstBlend = GL_ONE_MINUS_DST_ALPHA; break;
case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break;
case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break;
/* To compensate the lack of format switching with backbuffer offscreen rendering,
* and with onscreen rendering, we modify the alpha test parameters for (INV)DESTALPHA
* if the render target doesn't support alpha blending. A nonexistent alpha channel
* returns 1.0, so D3DBLEND_DESTALPHA is GL_ONE, and D3DBLEND_INVDESTALPHA is GL_ZERO
*/
case WINED3DBLEND_DESTALPHA :
rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
dstBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE;
break;
case WINED3DBLEND_INVDESTALPHA :
rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
dstBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
break;
case WINED3DBLEND_SRCALPHASAT :
dstBlend = GL_SRC_ALPHA_SATURATE;
WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
......@@ -291,12 +305,19 @@ static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break;
case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break;
case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break;
case WINED3DBLEND_DESTALPHA : srcBlend = GL_DST_ALPHA; break;
case WINED3DBLEND_INVDESTALPHA : srcBlend = GL_ONE_MINUS_DST_ALPHA; break;
case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break;
case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break;
case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break;
case WINED3DBLEND_DESTALPHA :
rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
srcBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE;
break;
case WINED3DBLEND_INVDESTALPHA :
rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
srcBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
break;
case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA;
dstBlend = GL_ONE_MINUS_SRC_ALPHA;
break;
......
......@@ -29,6 +29,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d);
/*****************************************************************************
* Pixel format array
*
* For the formats WINED3DFMT_A32B32G32R32F, WINED3DFMT_A16B16G16R16F,
* and WINED3DFMT_A16B16G16R16 do not have correct alpha masks, because the
* high masks do not fit into the 32 bit values needed for ddraw. It is only
* used for ddraw mostly, and to figure out if the format has alpha at all, so
* setting a mask like 0x1 for those surfaces is correct. The 64 and 128 bit
* formats are not usable in 2D rendering because ddraw doesn't support them.
*/
static const StaticPixelFormatDesc formats[] = {
/*{WINED3DFORMAT ,alphamask ,redmask ,greenmask ,bluemask ,bpp ,depth ,stencil, isFourcc*/
......@@ -47,13 +54,13 @@ static const StaticPixelFormatDesc formats[] = {
/* IEEE formats */
{WINED3DFMT_R32F ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,0 ,0 ,FALSE },
{WINED3DFMT_G32R32F ,0x0 ,0x0 ,0x0 ,0x0 ,8 ,0 ,0 ,FALSE },
{WINED3DFMT_A32B32G32R32F,0x0 ,0x0 ,0x0 ,0x0 ,16 ,0 ,0 ,FALSE },
{WINED3DFMT_A32B32G32R32F,0x1 ,0x0 ,0x0 ,0x0 ,16 ,0 ,0 ,FALSE },
/* Hmm? */
{WINED3DFMT_CxV8U8 ,0x0 ,0x0 ,0x0 ,0x0 ,2 ,0 ,0 ,FALSE },
/* Float */
{WINED3DFMT_R16F ,0x0 ,0x0 ,0x0 ,0x0 ,2 ,0 ,0 ,FALSE },
{WINED3DFMT_G16R16F ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,0 ,0 ,FALSE },
{WINED3DFMT_A16B16G16R16F,0x0 ,0x0 ,0x0 ,0x0 ,8 ,0 ,0 ,FALSE },
{WINED3DFMT_A16B16G16R16F,0x1 ,0x0 ,0x0 ,0x0 ,8 ,0 ,0 ,FALSE },
/* Palettized formats */
{WINED3DFMT_A8P8 ,0x0000ff00 ,0x0 ,0x0 ,0x0 ,2 ,0 ,0 ,FALSE },
{WINED3DFMT_P8 ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,0 ,0 ,FALSE },
......@@ -74,7 +81,7 @@ static const StaticPixelFormatDesc formats[] = {
{WINED3DFMT_X8B8G8R8 ,0x0 ,0x000000ff ,0x0000ff00 ,0x00ff0000 ,4 ,0 ,0 ,FALSE },
{WINED3DFMT_G16R16 ,0x0 ,0x0000ffff ,0xffff0000 ,0x0 ,4 ,0 ,0 ,FALSE },
{WINED3DFMT_A2R10G10B10 ,0xb0000000 ,0x3ff00000 ,0x000ffc00 ,0x000003ff ,4 ,0 ,0 ,FALSE },
{WINED3DFMT_A16B16G16R16,0x0 ,0x0000ffff ,0xffff0000 ,0x0 ,8 ,0 ,0 ,FALSE },
{WINED3DFMT_A16B16G16R16,0x1 ,0x0000ffff ,0xffff0000 ,0x0 ,8 ,0 ,0 ,FALSE },
/* Luminance */
{WINED3DFMT_L8 ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,0 ,0 ,FALSE },
{WINED3DFMT_A8L8 ,0x0000ff00 ,0x0 ,0x0 ,0x0 ,2 ,0 ,0 ,FALSE },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment