// FILE:        zcorruptccw.cpp
// DESC:        stencil conformance tests (counter clockwise flood)
// AUTHOR:      Todd M. Frost
// COMMENTS:    tests for z corruption due to stencil clear operations

#include "stencil.h"

// NAME:        CStencilZCorruptCCW()
// DESC:        stencil z corrupt ccw class constructor
// INPUT:       none
// OUTPUT:      none

CStencilZCorruptCCW::CStencilZCorruptCCW()
{
    m_szCommandKey = "ZCorruptCCW";
    m_nStipple = (UINT) 0;
}

// NAME:        ~CStencilZCorruptCCW()
// DESC:        stencil z corrupt ccw class destructor
// INPUT:       none
// OUTPUT:      none

CStencilZCorruptCCW::~CStencilZCorruptCCW()
{
}

// NAME:        CommandLineHelp()
// DESC:        command line help
// INPUT:       none
// OUTPUT:      none

VOID CStencilZCorruptCCW::CommandLineHelp(VOID)
{
    CStencil::CommandLineHelp();
}

// NAME:        CapsCheck()
// DESC:        caps check
// INPUT:       none
// OUTPUT:      true.....if caps check is successful
//              false....otherwise

bool CStencilZCorruptCCW::CapsCheck(VOID)
{
    if (m_pSrcDevice->GetCaps()->dwStencilCaps & D3DSTENCILCAPS_TWOSIDED)
        return CStencil::CapsCheck();
    else
        return false;
}

// NAME:        TestInitialize()
// DESC:        initialize test
// INPUT:       none
// OUTPUT:      uResult..result of test initialization

UINT CStencilZCorruptCCW::TestInitialize(VOID)
{
    UINT uResult = CStencil::TestInitialize();

    SetRenderState(D3DRS_STENCILFUNC, (DWORD) D3DCMP_NEVER);
    SetTestRange((UINT) 1, (UINT) (NMASKS*(m_dwStencilBitMask + 1)));
    return uResult;
}

// NAME:        ExecuteTest()
// DESC:        execute test
// INPUT:       uTest....test number
// OUTPUT:      true.....if test executed successfully
//              false....otherwise

bool CStencilZCorruptCCW::ExecuteTest(UINT uTest)
{
    bool bSuccess = false;
    D3DVALUE dvDepth = 0.0f;
    DWORD dwClear, dwFlags, dwInvert;
    DWORD dwMasks[2];
    UINT i, j;

    CStencil::ExecuteTest(uTest);
    dwMasks[0] = m_dwStencilBitMask;
    dwMasks[1] = 0xffffffff;

    for (j = 1, i = 0; (i < NMASKS) && !bSuccess; i++)
        for (dwClear = 0; dwClear <= m_dwStencilBitMask && !bSuccess; dwClear++, j++)
            if (j == uTest)
            {
                wsprintf(m_szBuffer, "Clear2() corruption:  0x%08X, 0x%08X, Non-Stippled", dwClear, dwMasks[i]);
                BeginTestCase(m_szBuffer, uTest);

                SetRenderState(D3DRS_CULLMODE, (DWORD) D3DCULL_NONE);

                SetRenderState(D3DRS_ZFUNC, (DWORD) D3DCMP_EQUAL);

                SetRenderState(D3DRS_STENCILENABLE, (DWORD) TRUE);
                SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, (DWORD) TRUE);
                SetRenderState(D3DRS_STENCILWRITEMASK, dwMasks[i]);

                SetRenderState(D3DRS_CCW_STENCILFUNC, (DWORD) D3DCMP_ALWAYS);
                SetRenderState(D3DRS_CCW_STENCILFAIL, (DWORD) D3DSTENCILOP_KEEP);
                SetRenderState(D3DRS_CCW_STENCILZFAIL, (DWORD) D3DSTENCILOP_KEEP);
                SetRenderState(D3DRS_CCW_STENCILPASS, (DWORD) D3DSTENCILOP_KEEP);

                dwFlags = D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL;

                if (BeginScene(dvDepth, dwClear, m_dwPassColor, dwFlags))
                {
                    if (EndScene())
                    {
                        dwFlags = D3DCLEAR_TARGET | D3DCLEAR_STENCIL;
                        dwInvert = m_dwStencilBitMask & ~dwClear;

                        if (BeginScene(dvDepth, dwInvert, m_dwPassColor, dwFlags))
                        {
                            SetRenderState(D3DRS_ZFUNC, (DWORD) D3DCMP_NOTEQUAL);

                            SetRenderState(D3DRS_CCW_STENCILFUNC, (DWORD) D3DCMP_ALWAYS);

                            Flood(dvDepth, m_dwFailColor, FLOOD_CCW);
        
                            if (EndScene())
                            {
                                if (Compare())
                                    Pass();
                                else
                                {
                                    WriteToLog("Invalid pixel detected.\n");
                                    Fail();
                                }
                            }
                            else
                            {
                                WriteToLog("EndScene() failed: %s.\n", GLE(GetLastError()));
                                Fail();
                            }
                        }
                        else
                        {
                            WriteToLog("BeginScene() failed: %s.\n", GLE(GetLastError()));
                            Fail();
                        }
                    }
                    else
                    {
                        WriteToLog("EndScene() failed: %s.\n", GLE(GetLastError()));
                        Fail();
                    }
                }
                else
                {
                    WriteToLog("BeginScene() failed: %s.\n", GLE(GetLastError()));
                    Fail();
                }

                bSuccess = true;
            }

    return bSuccess;
}
