Stefan Dösinger : wined3d: D3DTOP_DOTPRODUCT3 colorop overrides the alphaop.
Alexandre Julliard
julliard at winehq.org
Wed Aug 27 08:24:46 CDT 2008
Module: wine
Branch: master
Commit: b294e43206dab65687dd9358f4a1c8ae396ab7fe
URL: http://source.winehq.org/git/wine.git/?a=commit;h=b294e43206dab65687dd9358f4a1c8ae396ab7fe
Author: Stefan Dösinger <stefan at codeweavers.com>
Date: Tue Aug 26 14:11:47 2008 -0500
wined3d: D3DTOP_DOTPRODUCT3 colorop overrides the alphaop.
Note that the fix is only implemented in the arbfp and atifs fragment
pipeline. Unfortunately nvrc doesn't support dot3 as alpha operation.
---
dlls/d3d9/tests/visual.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++
dlls/wined3d/utils.c | 16 ++++++++--
2 files changed, 91 insertions(+), 3 deletions(-)
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index d36411f..c889e7e 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -9576,6 +9576,82 @@ static void alphareplicate_test(IDirect3DDevice9 *device) {
}
+static void dp3_alpha_test(IDirect3DDevice9 *device) {
+ HRESULT hr;
+ D3DCAPS9 caps;
+ DWORD color;
+ struct vertex quad[] = {
+ { -1.0, -1.0, 0.1, 0x408080c0 },
+ { 1.0, -1.0, 0.1, 0x408080c0 },
+ { -1.0, 1.0, 0.1, 0x408080c0 },
+ { 1.0, 1.0, 0.1, 0x408080c0 },
+ };
+
+ memset(&caps, 0, sizeof(caps));
+ hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
+ ok(SUCCEEDED(hr), "GetDeviceCaps failed with 0x%08x\n", hr);
+ if (!(caps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3)) {
+ skip("D3DTOP_DOTPRODUCT3 not supported\n");
+ return;
+ }
+
+ hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
+ ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
+
+ hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
+ ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
+
+ /* dp3_x4 r0, diffuse_bias, tfactor_bias
+ * mov r0.a, diffuse.a
+ * mov r0, r0.a
+ *
+ * It turns out that the 2nd line is ignored, and the dp3 result written into r0.a instead
+ * thus with input vec4(0.5, 0.5, 0.75, 0.25) and vec4(1.0, 1.0, 1.0, 1.0) the result is
+ * (0.0 * 0.5 + 0.0 * 0.5 + 0.25 * 0.5) * 4 = 0.125 * 4 = 0.5, with a bunch of inprecision.
+ */
+ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3);
+ ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
+ ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
+ ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
+ ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_CURRENT | D3DTA_ALPHAREPLICATE);
+ ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
+ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0xffffffff);
+ ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
+
+ hr = IDirect3DDevice9_BeginScene(device);
+ ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
+ if(SUCCEEDED(hr)) {
+ hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
+ ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
+ hr = IDirect3DDevice9_EndScene(device);
+ ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
+ }
+
+ hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
+ ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
+
+ color = getPixelColor(device, 320, 240);
+ ok(color_match(color, 0x00808080, 4), "dp3 alpha test 0x%08x, expected 0x00808080\n",
+ color);
+
+ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
+ hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
+}
+
START_TEST(visual)
{
IDirect3DDevice9 *device_ptr;
@@ -9732,9 +9808,11 @@ START_TEST(visual)
}
}
else skip("No ps_1_1 support\n");
+
texop_test(device_ptr);
texop_range_test(device_ptr);
alphareplicate_test(device_ptr);
+ dp3_alpha_test(device_ptr);
cleanup:
if(device_ptr) {
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 8501544..3cce302 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -1871,9 +1871,19 @@ void gen_ffp_op(IWineD3DStateBlockImpl *stateblock, struct ffp_settings *setting
cop = WINED3DTOP_SELECTARG1;
}
- aarg1 = (args[aop] & ARG1) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG1] : 0xffffffff;
- aarg2 = (args[aop] & ARG2) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG2] : 0xffffffff;
- aarg0 = (args[aop] & ARG0) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG0] : 0xffffffff;
+ if(cop == WINED3DTOP_DOTPRODUCT3) {
+ /* A dotproduct3 on the colorop overwrites the alphaop operation and replicates
+ * the color result to the alpha component of the destination
+ */
+ aop = cop;
+ aarg1 = carg1;
+ aarg2 = carg2;
+ aarg0 = carg0;
+ } else {
+ aarg1 = (args[aop] & ARG1) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG1] : 0xffffffff;
+ aarg2 = (args[aop] & ARG2) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG2] : 0xffffffff;
+ aarg0 = (args[aop] & ARG0) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG0] : 0xffffffff;
+ }
if(i == 0 && stateblock->textures[0] &&
stateblock->renderState[WINED3DRS_COLORKEYENABLE] &&
More information about the wine-cvs
mailing list