windows-nt/Source/XPSP1/NT/multimedia/directx/dxg/ref8/hop/drawgrid.cpp
2020-09-26 16:20:57 +08:00

1699 lines
58 KiB
C++

/*============================================================================
*
* Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
*
* File: drawgrid.cpp
* Content: Implementation for high order surfaces
*
****************************************************************************/
#include "pch.cpp"
#pragma hdrstop
//-----------------------------------------------------------------------------
// RDHOCoeffs::operator=
//-----------------------------------------------------------------------------
RDHOCoeffs& RDHOCoeffs::operator=(const RDHOCoeffs &coeffs)
{
m_Width = coeffs.m_Width;
m_Height = coeffs.m_Height;
m_Stride = coeffs.m_Stride;
m_Basis = coeffs.m_Basis;
m_Order = coeffs.m_Order;
if(coeffs.m_pNumSegs != 0)
{
m_pNumSegs = new FLOAT[4];
if(m_pNumSegs != 0)
{
memcpy(m_pNumSegs, coeffs.m_pNumSegs, sizeof(FLOAT) * 4);
}
}
else
{
m_pNumSegs = 0;
}
for(unsigned i = 0; i < RD_MAX_NUMSTREAMS; ++i)
{
if(coeffs.m_pData[i] != 0)
{
m_DataSize[i] = coeffs.m_DataSize[i];
m_pData[i] = new BYTE[m_DataSize[i]];
if(m_pData[i] != 0)
{
memcpy(m_pData[i], coeffs.m_pData[i], m_DataSize[i]);
}
}
else
{
m_pData[i] = 0;
}
}
return *this;
}
//-----------------------------------------------------------------------------
// RefDev::DrawRectPatch
//-----------------------------------------------------------------------------
HRESULT
RefDev::DrawRectPatch( LPD3DHAL_DP2DRAWRECTPATCH pDP )
{
HRESULT hr = S_OK;
if( RDVSD_ISLEGACY( m_CurrentVShaderHandle ) )
{
//
// The legacy FVF style: The Zero'th Stream is implied
//
DWORD dwFVF = m_CurrentVShaderHandle;
RDVStream& Stream = m_VStream[0];
DWORD dwStride = Stream.m_dwStride;
DWORD dwFVFSize = GetFVFVertexSize( dwFVF );
if( Stream.m_pData == NULL || dwStride == 0 )
{
DPFERR("Zero'th stream doesnt have valid VB set");
return DDERR_INVALIDPARAMS;
}
if( dwStride < dwFVFSize )
{
DPFERR("The stride set for the vertex stream is less than the FVF vertex size");
return E_FAIL;
}
}
FLOAT *pSegs;
D3DRECTPATCH_INFO Info, *pInfo;
BYTE *TempData[RD_MAX_NUMSTREAMS + 1];
if(pDP->Handle != 0)
{
if((pDP->Flags & RTPATCHFLAG_HASINFO) != 0) // Is either a first time or a recompute
{
HR_RET( m_HOSCoeffs.Grow(pDP->Handle) );
if((pDP->Flags & RTPATCHFLAG_HASSEGS) != 0)
{
pInfo = (D3DRECTPATCH_INFO*)(((BYTE*)(pDP + 1) + sizeof(FLOAT) * 4));
pSegs = (FLOAT*)(pDP + 1);
}
else
{
pInfo = (D3DRECTPATCH_INFO*)(pDP + 1);
pSegs = 0;
}
RDHOCoeffs &coeffs = m_HOSCoeffs[pDP->Handle];
coeffs.m_Width = pInfo->Width;
coeffs.m_Height = pInfo->Height;
coeffs.m_Stride = pInfo->Width;
coeffs.m_Basis = pInfo->Basis;
coeffs.m_Order = pInfo->Order;
delete[] coeffs.m_pNumSegs;
if(pSegs != 0)
{
coeffs.m_pNumSegs = new FLOAT[4];
if(coeffs.m_pNumSegs == 0)
{
return E_OUTOFMEMORY;
}
memcpy(coeffs.m_pNumSegs, pSegs, sizeof(FLOAT) * 4);
}
else
{
coeffs.m_pNumSegs = 0;
}
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
{
RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
if(StreamDecl.m_dwStreamIndex < RD_MAX_NUMSTREAMS) // ignore the implicit stream
{
RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
delete[] coeffs.m_pData[StreamDecl.m_dwStreamIndex];
coeffs.m_DataSize[StreamDecl.m_dwStreamIndex] = pInfo->Width * pInfo->Height * Stream.m_dwStride;
coeffs.m_pData[StreamDecl.m_dwStreamIndex] = new BYTE[coeffs.m_DataSize[StreamDecl.m_dwStreamIndex]];
if(coeffs.m_pData[StreamDecl.m_dwStreamIndex] == 0)
{
return E_OUTOFMEMORY;
}
for(unsigned k = 0; k < pInfo->Height; ++k)
{
memcpy(&coeffs.m_pData[StreamDecl.m_dwStreamIndex][k * pInfo->Width * Stream.m_dwStride],
&Stream.m_pData[((pInfo->StartVertexOffsetHeight + k) * pInfo->Stride + pInfo->StartVertexOffsetWidth) * Stream.m_dwStride],
pInfo->Width * Stream.m_dwStride);
}
}
}
}
// Guard against bad handles
if(pDP->Handle >= m_HOSCoeffs.GetSize())
{
DPFERR("Invalid patch handle specified in Draw*Patch call");
return E_FAIL;
}
RDHOCoeffs &coeffs = m_HOSCoeffs[pDP->Handle];
Info.StartVertexOffsetWidth = 0;
Info.StartVertexOffsetHeight = 0;
Info.Width = coeffs.m_Width;
Info.Height = coeffs.m_Height;
Info.Stride = coeffs.m_Stride;
Info.Basis = coeffs.m_Basis;
Info.Order = coeffs.m_Order;
pInfo = &Info;
if((pDP->Flags & RTPATCHFLAG_HASSEGS) != 0)
{
pSegs = (FLOAT*)(pDP + 1);
}
else
{
pSegs = coeffs.m_pNumSegs;
}
// Save current data stream pointers and replace with
// pointer to tessellation output
hr = LinkCachedTessellatorOutput(pDP->Handle, TempData);
}
else
{
if((pDP->Flags & RTPATCHFLAG_HASINFO) == 0)
{
DPFERR("Need patch info if handle is zero");
return DDERR_INVALIDPARAMS;
}
if((pDP->Flags & RTPATCHFLAG_HASSEGS) != 0)
{
pInfo = (D3DRECTPATCH_INFO*)(((BYTE*)(pDP + 1) + sizeof(FLOAT) * 4));
pSegs = (FLOAT*)(pDP + 1);
}
else
{
pInfo = (D3DRECTPATCH_INFO*)(pDP + 1);
pSegs = 0;
}
// Save current data stream pointers and replace with
// pointer to tessellation output
hr = LinkTessellatorOutput();
}
if( SUCCEEDED(hr) )
{
switch(pInfo->Basis)
{
case D3DBASIS_BSPLINE:
hr = ProcessBSpline(pInfo->StartVertexOffsetWidth, pInfo->StartVertexOffsetHeight,
pInfo->Width, pInfo->Height,
pInfo->Stride, pInfo->Order,
pSegs);
break;
case D3DBASIS_BEZIER:
hr = ProcessBezier(pInfo->StartVertexOffsetWidth, pInfo->StartVertexOffsetHeight,
pInfo->Width, pInfo->Height,
pInfo->Stride, pInfo->Order,
pSegs,
false);
break;
case D3DBASIS_INTERPOLATE:
hr = ProcessCatRomSpline(pInfo->StartVertexOffsetWidth, pInfo->StartVertexOffsetHeight,
pInfo->Width, pInfo->Height,
pInfo->Stride,
pSegs);
break;
default:
hr = E_NOTIMPL;
}
}
if(pDP->Handle != 0)
{
// Restore back saved pointer
UnlinkCachedTessellatorOutput(TempData);
}
else
{
// Restore back saved pointer
UnlinkTessellatorOutput();
}
return hr;
}
//-----------------------------------------------------------------------------
// RefDev::ConvertLinearTriBezierToRectBezier
//-----------------------------------------------------------------------------
HRESULT
RefDev::ConvertLinearTriBezierToRectBezier(DWORD dwDataType, const BYTE *B, DWORD dwStride, BYTE *Q)
{
DWORD dwElements = 0;
switch(dwDataType)
{
case D3DVSDT_FLOAT4:
++dwElements;
case D3DVSDT_FLOAT3:
++dwElements;
case D3DVSDT_FLOAT2:
++dwElements;
case D3DVSDT_FLOAT1:
++dwElements;
{
// Replicate first point twice to get a singular edge
for(unsigned i = 0; i < 2; ++i)
{
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
}
B += dwStride;
// Finally we just copy the last row
for(i = 0; i < 2; ++i)
{
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
B += dwStride;
}
}
break;
case D3DVSDT_D3DCOLOR:
case D3DVSDT_UBYTE4:
dwElements = 4;
{
// Replicate first point twice to get a singular edge
for(unsigned i = 0; i < 2; ++i)
{
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
}
B += dwStride;
// Finally we just copy the last row
for(i = 0; i < 2; ++i)
{
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
B += dwStride;
}
}
break;
case D3DVSDT_SHORT4:
dwElements += 2;
case D3DVSDT_SHORT2:
dwElements += 2;
{
// Replicate first point twice to get a singular edge
for(unsigned i = 0; i < 2; ++i)
{
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
}
B += dwStride;
// Finally we just copy the last row
for(i = 0; i < 2; ++i)
{
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
B += dwStride;
}
}
break;
default:
_ASSERT(FALSE, "Ununderstood vertex element data type");
return DDERR_INVALIDPARAMS;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// RefDev::ConvertCubicTriBezierToRectBezier
//-----------------------------------------------------------------------------
HRESULT
RefDev::ConvertCubicTriBezierToRectBezier(DWORD dwDataType, const BYTE *B, DWORD dwStride, BYTE *Q)
{
DWORD dwElements = 0;
switch(dwDataType)
{
case D3DVSDT_FLOAT4:
++dwElements;
case D3DVSDT_FLOAT3:
++dwElements;
case D3DVSDT_FLOAT2:
++dwElements;
case D3DVSDT_FLOAT1:
++dwElements;
{
// Replicate first point four times to get a singular edge
for(unsigned i = 0; i < 4; ++i)
{
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
}
B += dwStride;
// For the next row, we simply copy the second point
// followed by two interpolated control points
// followed by the third point
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
FLOAT *B021 = (FLOAT*)B, *B120 = (FLOAT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B021[i] * 2.0 + B120[i]) / 3.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B021[i] + B120[i] * 2.0) / 3.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
B += dwStride;
// Again, we copy the edge points and interpolate
// the central ones
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
FLOAT *B012 = (FLOAT*)B, *B111 = (FLOAT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B012[i] + B111[i] * 2.0) / 3.0);
}
Q += dwStride;
B += dwStride;
FLOAT *B210 = (FLOAT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B111[i] * 2.0 + B210[i]) / 3.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
B += dwStride;
// Finally we just copy the last row
for(i = 0; i < 4; ++i)
{
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
B += dwStride;
}
}
break;
case D3DVSDT_D3DCOLOR:
case D3DVSDT_UBYTE4:
dwElements = 4;
{
// Replicate first point four times to get a singular edge
for(unsigned i = 0; i < 4; ++i)
{
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
}
B += dwStride;
// For the next row, we simply copy the second point
// followed by two interpolated control points
// followed by the third point
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
BYTE *B021 = (BYTE*)B, *B120 = (BYTE*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B021[i] * 2.0 + B120[i]) / 3.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B021[i] + B120[i] * 2.0) / 3.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
B += dwStride;
// Again, we copy the edge points and interpolate
// the central ones
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
BYTE *B012 = (BYTE*)B, *B111 = (BYTE*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B012[i] + B111[i] * 2.0) / 3.0);
}
Q += dwStride;
B += dwStride;
BYTE *B210 = (BYTE*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B111[i] * 2.0 + B210[i]) / 3.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
B += dwStride;
// Finally we just copy the last row
for(i = 0; i < 4; ++i)
{
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
B += dwStride;
}
}
break;
case D3DVSDT_SHORT4:
dwElements += 2;
case D3DVSDT_SHORT2:
dwElements += 2;
{
// Replicate first point four times to get a singular edge
for(unsigned i = 0; i < 4; ++i)
{
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
}
B += dwStride;
// For the next row, we simply copy the second point
// followed by two interpolated control points
// followed by the third point
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
SHORT *B021 = (SHORT*)B, *B120 = (SHORT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B021[i] * 2.0 + B120[i]) / 3.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B021[i] + B120[i] * 2.0) / 3.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
B += dwStride;
// Again, we copy the edge points and interpolate
// the central ones
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
SHORT *B012 = (SHORT*)B, *B111 = (SHORT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B012[i] + B111[i] * 2.0) / 3.0);
}
Q += dwStride;
B += dwStride;
SHORT *B210 = (SHORT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B111[i] * 2.0 + B210[i]) / 3.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
B += dwStride;
// Finally we just copy the last row
for(i = 0; i < 4; ++i)
{
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
B += dwStride;
}
}
break;
default:
_ASSERT(FALSE, "Ununderstood vertex element data type");
return DDERR_INVALIDPARAMS;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// RefDev::ConvertQuinticTriBezierToRectBezier
//-----------------------------------------------------------------------------
HRESULT
RefDev::ConvertQuinticTriBezierToRectBezier(DWORD dwDataType, const BYTE *B, DWORD dwStride, BYTE *Q)
{
DWORD dwElements = 0;
switch(dwDataType)
{
case D3DVSDT_FLOAT4:
++dwElements;
case D3DVSDT_FLOAT3:
++dwElements;
case D3DVSDT_FLOAT2:
++dwElements;
case D3DVSDT_FLOAT1:
++dwElements;
{
// Replicate first point six times to get a singular edge
for(unsigned i = 0; i < 6; ++i)
{
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
}
B += dwStride;
// For the next row, we simply copy the second point
// followed by four interpolated control points
// followed by the fifth point
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
FLOAT *B041 = (FLOAT*)B, *B140 = (FLOAT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B041[i] * 4.0 + B140[i]) / 5.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B041[i] * 3.0 + B140[i] * 2.0) / 5.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B041[i] * 2.0 + B140[i] * 3.0) / 5.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B041[i] + B140[i] * 4.0) / 5.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
B += dwStride;
// Again, we copy the edge points and interpolate
// the central ones
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
FLOAT *B032 = (FLOAT*)B, *B131 = (FLOAT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B032[i] * 3.0 + B131[i] * 2.0) / 5.0);
}
Q += dwStride;
B += dwStride;
FLOAT *B230 = (FLOAT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B032[i] * 3.0 + B131[i] * 6.0 + B230[i]) / 10.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B032[i] + B131[i] * 6.0 + B230[i] * 3.0) / 10.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B131[i] * 2.0 + B230[i] * 3.0) / 5.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
B += dwStride;
// Again, we copy the edge points and interpolate
// the central ones
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
FLOAT *B023 = (FLOAT*)B, *B122 = (FLOAT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B023[i] * 2.0 + B122[i] * 3.0) / 5.0);
}
Q += dwStride;
B += dwStride;
FLOAT *B221 = (FLOAT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B023[i] + B122[i] * 6.0 + B221[i] * 3.0) / 10.0);
}
Q += dwStride;
B += dwStride;
FLOAT *B320 = (FLOAT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B122[i] * 3.0 + B221[i] * 6.0 + B320[i]) / 10.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B221[i] * 3.0 + B320[i] * 2.0) / 5.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
B += dwStride;
// Again, we copy the edge points and interpolate
// the central ones
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
FLOAT *B014 = (FLOAT*)B, *B113 = (FLOAT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B014[i] + B113[i] * 4.0) / 5.0);
}
Q += dwStride;
B += dwStride;
FLOAT *B212 = (FLOAT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B113[i] * 2.0 + B212[i] * 3.0) / 5.0);
}
Q += dwStride;
B += dwStride;
FLOAT *B311 = (FLOAT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B212[i] * 3.0 + B311[i] * 2.0) / 5.0);
}
Q += dwStride;
B += dwStride;
FLOAT *B410 = (FLOAT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((FLOAT*)Q)[i] = FLOAT((B311[i] * 4.0 + B410[i]) / 5.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
B += dwStride;
// Finally we just copy the last row
for(i = 0; i < 6; ++i)
{
memcpy(Q, B, sizeof(FLOAT) * dwElements);
Q += dwStride;
B += dwStride;
}
}
break;
case D3DVSDT_UBYTE4:
case D3DVSDT_D3DCOLOR:
dwElements = 4;
{
// Replicate first point six times to get a singular edge
for(unsigned i = 0; i < 6; ++i)
{
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
}
B += dwStride;
// For the next row, we simply copy the second point
// followed by four interpolated control points
// followed by the fifth point
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
BYTE *B041 = (BYTE*)B, *B140 = (BYTE*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B041[i] * 4.0 + B140[i]) / 5.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B041[i] * 3.0 + B140[i] * 2.0) / 5.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B041[i] * 2.0 + B140[i] * 3.0) / 5.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B041[i] + B140[i] * 4.0) / 5.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
B += dwStride;
// Again, we copy the edge points and interpolate
// the central ones
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
BYTE *B032 = (BYTE*)B, *B131 = (BYTE*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B032[i] * 3.0 + B131[i] * 2.0) / 5.0);
}
Q += dwStride;
B += dwStride;
BYTE *B230 = (BYTE*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B032[i] * 3.0 + B131[i] * 6.0 + B230[i]) / 10.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B032[i] + B131[i] * 6.0 + B230[i] * 3.0) / 10.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B131[i] * 2.0 + B230[i] * 3.0) / 5.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
B += dwStride;
// Again, we copy the edge points and interpolate
// the central ones
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
BYTE *B023 = (BYTE*)B, *B122 = (BYTE*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B023[i] * 2.0 + B122[i] * 3.0) / 5.0);
}
Q += dwStride;
B += dwStride;
BYTE *B221 = (BYTE*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B023[i] + B122[i] * 6.0 + B221[i] * 3.0) / 10.0);
}
Q += dwStride;
B += dwStride;
BYTE *B320 = (BYTE*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B122[i] * 3.0 + B221[i] * 6.0 + B320[i]) / 10.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B221[i] * 3.0 + B320[i] * 2.0) / 5.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
B += dwStride;
// Again, we copy the edge points and interpolate
// the central ones
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
BYTE *B014 = (BYTE*)B, *B113 = (BYTE*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B014[i] + B113[i] * 4.0) / 5.0);
}
Q += dwStride;
B += dwStride;
BYTE *B212 = (BYTE*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B113[i] * 2.0 + B212[i] * 3.0) / 5.0);
}
Q += dwStride;
B += dwStride;
BYTE *B311 = (BYTE*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B212[i] * 3.0 + B311[i] * 2.0) / 5.0);
}
Q += dwStride;
B += dwStride;
BYTE *B410 = (BYTE*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((BYTE*)Q)[i] = BYTE((B311[i] * 4.0 + B410[i]) / 5.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
B += dwStride;
// Finally we just copy the last row
for(i = 0; i < 6; ++i)
{
memcpy(Q, B, sizeof(BYTE) * dwElements);
Q += dwStride;
B += dwStride;
}
}
break;
case D3DVSDT_SHORT4:
dwElements += 2;
case D3DVSDT_SHORT2:
dwElements += 2;
{
// Replicate first point six times to get a singular edge
for(unsigned i = 0; i < 6; ++i)
{
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
}
B += dwStride;
// For the next row, we simply copy the second point
// followed by four interpolated control points
// followed by the fifth point
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
SHORT *B041 = (SHORT*)B, *B140 = (SHORT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B041[i] * 4.0 + B140[i]) / 5.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B041[i] * 3.0 + B140[i] * 2.0) / 5.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B041[i] * 2.0 + B140[i] * 3.0) / 5.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B041[i] + B140[i] * 4.0) / 5.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
B += dwStride;
// Again, we copy the edge points and interpolate
// the central ones
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
SHORT *B032 = (SHORT*)B, *B131 = (SHORT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B032[i] * 3.0 + B131[i] * 2.0) / 5.0);
}
Q += dwStride;
B += dwStride;
SHORT *B230 = (SHORT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B032[i] * 3.0 + B131[i] * 6.0 + B230[i]) / 10.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B032[i] + B131[i] * 6.0 + B230[i] * 3.0) / 10.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B131[i] * 2.0 + B230[i] * 3.0) / 5.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
B += dwStride;
// Again, we copy the edge points and interpolate
// the central ones
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
SHORT *B023 = (SHORT*)B, *B122 = (SHORT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B023[i] * 2.0 + B122[i] * 3.0) / 5.0);
}
Q += dwStride;
B += dwStride;
SHORT *B221 = (SHORT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B023[i] + B122[i] * 6.0 + B221[i] * 3.0) / 10.0);
}
Q += dwStride;
B += dwStride;
SHORT *B320 = (SHORT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B122[i] * 3.0 + B221[i] * 6.0 + B320[i]) / 10.0);
}
Q += dwStride;
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B221[i] * 3.0 + B320[i] * 2.0) / 5.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
B += dwStride;
// Again, we copy the edge points and interpolate
// the central ones
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
SHORT *B014 = (SHORT*)B, *B113 = (SHORT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B014[i] + B113[i] * 4.0) / 5.0);
}
Q += dwStride;
B += dwStride;
SHORT *B212 = (SHORT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B113[i] * 2.0 + B212[i] * 3.0) / 5.0);
}
Q += dwStride;
B += dwStride;
SHORT *B311 = (SHORT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B212[i] * 3.0 + B311[i] * 2.0) / 5.0);
}
Q += dwStride;
B += dwStride;
SHORT *B410 = (SHORT*)(B + dwStride);
for(i = 0; i < dwElements; ++i)
{
((SHORT*)Q)[i] = SHORT((B311[i] * 4.0 + B410[i]) / 5.0);
}
Q += dwStride;
B += dwStride;
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
B += dwStride;
// Finally we just copy the last row
for(i = 0; i < 6; ++i)
{
memcpy(Q, B, sizeof(SHORT) * dwElements);
Q += dwStride;
B += dwStride;
}
}
break;
default:
_ASSERT(FALSE, "Ununderstood vertex element data type");
return DDERR_INVALIDPARAMS;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// RefDev::DrawTriPatch
//-----------------------------------------------------------------------------
HRESULT
RefDev::DrawTriPatch( LPD3DHAL_DP2DRAWTRIPATCH pDP )
{
HRESULT hr = S_OK;
if( RDVSD_ISLEGACY( m_CurrentVShaderHandle ) )
{
//
// The legacy FVF style: The Zero'th Stream is implied
//
DWORD dwFVF = m_CurrentVShaderHandle;
RDVStream& Stream = m_VStream[0];
DWORD dwStride = Stream.m_dwStride;
DWORD dwFVFSize = GetFVFVertexSize( dwFVF );
if( Stream.m_pData == NULL || dwStride == 0 )
{
DPFERR("Zero'th stream doesnt have valid VB set");
return DDERR_INVALIDPARAMS;
}
if( dwStride < dwFVFSize )
{
DPFERR("The stride set for the vertex stream is less than the FVF vertex size");
return E_FAIL;
}
}
FLOAT *pSegs;
D3DRECTPATCH_INFO Info;
BYTE *TempData[RD_MAX_NUMSTREAMS + 1];
if(pDP->Handle == 0 && (pDP->Flags & RTPATCHFLAG_HASINFO) == 0)
{
DPFERR("Need patch info if handle is zero");
return DDERR_INVALIDPARAMS;
}
if((pDP->Flags & RTPATCHFLAG_HASINFO) != 0) // Is either a first time or a recompute
{
HR_RET( m_HOSCoeffs.Grow(pDP->Handle) );
D3DTRIPATCH_INFO *pInfo;
if((pDP->Flags & RTPATCHFLAG_HASSEGS) != 0)
{
pInfo = (D3DTRIPATCH_INFO*)(((BYTE*)(pDP + 1) + sizeof(FLOAT) * 3));
pSegs = (FLOAT*)(pDP + 1);
}
else
{
pInfo = (D3DTRIPATCH_INFO*)(pDP + 1);
pSegs = 0;
}
RDHOCoeffs &coeffs = m_HOSCoeffs[pDP->Handle];
coeffs.m_Width = (DWORD)pInfo->Order + 1;
coeffs.m_Height = (DWORD)pInfo->Order + 1;
coeffs.m_Stride = (DWORD)pInfo->Order + 1;
coeffs.m_Basis = pInfo->Basis;
coeffs.m_Order = pInfo->Order;
delete[] coeffs.m_pNumSegs;
if(pSegs != 0)
{
coeffs.m_pNumSegs = new FLOAT[4];
if(coeffs.m_pNumSegs == 0)
{
return E_OUTOFMEMORY;
}
coeffs.m_pNumSegs[0] = pSegs[2];
memcpy(&coeffs.m_pNumSegs[1], pSegs, sizeof(FLOAT) * 3);
}
else
{
coeffs.m_pNumSegs = 0;
}
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
// Allocate memory to hold rect patches rather than tri patches
for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
{
RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
if(StreamDecl.m_dwStreamIndex < RD_MAX_NUMSTREAMS) // ignore the implicit stream
{
RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
delete[] coeffs.m_pData[StreamDecl.m_dwStreamIndex];
coeffs.m_DataSize[StreamDecl.m_dwStreamIndex] = coeffs.m_Width * coeffs.m_Height * Stream.m_dwStride;
coeffs.m_pData[StreamDecl.m_dwStreamIndex] = new BYTE[coeffs.m_DataSize[StreamDecl.m_dwStreamIndex]];
if(coeffs.m_pData[StreamDecl.m_dwStreamIndex] == 0)
{
return E_OUTOFMEMORY;
}
}
}
// Now go through tri patch data, convert it to rect patch and store it in
// in the space that we allocated above
for(unsigned e = 0; e < Decl.m_dwNumElements; ++e)
{
RDVElement &velem = Decl.m_VertexElements[e];
if(!velem.m_bIsTessGen)
{
RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
LPBYTE Q = coeffs.m_pData[velem.m_dwStreamIndex] + velem.m_dwOffset;
LPBYTE B = vstream.m_pData + pInfo->StartVertexOffset * vstream.m_dwStride + velem.m_dwOffset;
if(pInfo->Order == D3DORDER_LINEAR)
{
hr = ConvertLinearTriBezierToRectBezier(velem.m_dwDataType, B, vstream.m_dwStride, Q);
if(FAILED(hr))
{
DPFERR("Conversion from Linear Tri Patch to Rect Patch failed");
return E_FAIL;
}
}
else if(pInfo->Order == D3DORDER_CUBIC)
{
hr = ConvertCubicTriBezierToRectBezier(velem.m_dwDataType, B, vstream.m_dwStride, Q);
if(FAILED(hr))
{
DPFERR("Conversion from Cubic Tri Patch to Rect Patch failed");
return E_FAIL;
}
}
else if(pInfo->Order == D3DORDER_QUINTIC)
{
hr = ConvertQuinticTriBezierToRectBezier(velem.m_dwDataType, B, vstream.m_dwStride, Q);
if(FAILED(hr))
{
DPFERR("Conversion from Quintic Tri Patch to Rect Patch failed");
return E_FAIL;
}
}
else
{
DPFERR("Only cubic Bezier patches currently supported");
return E_FAIL;
}
}
}
}
// Guard against bad handles
if(pDP->Handle >= m_HOSCoeffs.GetSize())
{
DPFERR("Invalid patch handle specified in Draw*Patch call");
return E_FAIL;
}
RDHOCoeffs &coeffs = m_HOSCoeffs[pDP->Handle];
Info.StartVertexOffsetWidth = 0;
Info.StartVertexOffsetHeight = 0;
Info.Width = coeffs.m_Width;
Info.Height = coeffs.m_Height;
Info.Stride = coeffs.m_Stride;
Info.Basis = coeffs.m_Basis;
Info.Order = coeffs.m_Order;
D3DRECTPATCH_INFO *pInfo = &Info;
FLOAT Segs[4];
if((pDP->Flags & RTPATCHFLAG_HASSEGS) != 0)
{
Segs[0] = ((FLOAT*)(pDP + 1))[2];
memcpy(&Segs[1], pDP + 1, sizeof(FLOAT) * 3);
pSegs = &Segs[0];
}
else
{
pSegs = coeffs.m_pNumSegs;
}
// Save current data stream pointers and replace with
// pointer to tessellation output
hr = LinkCachedTessellatorOutput(pDP->Handle, TempData);
if( SUCCEEDED(hr) )
{
switch(pInfo->Basis)
{
case D3DBASIS_BEZIER:
hr = ProcessBezier(pInfo->StartVertexOffsetWidth, pInfo->StartVertexOffsetHeight,
pInfo->Width, pInfo->Height,
pInfo->Stride, pInfo->Order,
pSegs,
true);
break;
default:
hr = E_NOTIMPL;
}
}
// Restore back saved pointer
UnlinkCachedTessellatorOutput(TempData);
return hr;
}
//---------------------------------------------------------------------
// RefDev::LinkTessellatorOutput
//---------------------------------------------------------------------
HRESULT RefDev::LinkTessellatorOutput()
{
HRESULT hr = S_OK;
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
{
RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
// Make space for four vertices
hr |= Stream.m_TessOut.Grow(StreamDecl.m_dwStride * 4);
Stream.m_pSavedData = Stream.m_pData;
Stream.m_pData = &Stream.m_TessOut[0];
}
return hr;
}
//---------------------------------------------------------------------
// RefDev::LinkCachedTessellatorOutput
//---------------------------------------------------------------------
HRESULT RefDev::LinkCachedTessellatorOutput(DWORD Handle, BYTE **pTempData)
{
HRESULT hr = S_OK;
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
{
RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
// Make space for four vertices
hr |= Stream.m_TessOut.Grow(StreamDecl.m_dwStride * 4);
if(StreamDecl.m_dwStreamIndex < RD_MAX_NUMSTREAMS) // ignore the implicit stream
{
Stream.m_pSavedData = m_HOSCoeffs[Handle].m_pData[StreamDecl.m_dwStreamIndex];
if(Stream.m_pSavedData == 0)
{
DPFERR("Deleted or unspecified patch was requested to be drawn");
hr |= E_FAIL;
}
}
else
{
Stream.m_pSavedData = 0;
}
pTempData[StreamDecl.m_dwStreamIndex] = Stream.m_pData;
Stream.m_pData = &Stream.m_TessOut[0];
}
return hr;
}
//---------------------------------------------------------------------
// RefDev::UnlinkTessellatorOuput
//---------------------------------------------------------------------
void RefDev::UnlinkTessellatorOutput()
{
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
{
RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
Stream.m_pData = Stream.m_pSavedData;
Stream.m_pSavedData = NULL;
}
}
//---------------------------------------------------------------------
// RefDev::UnlinkTessellatorOuput
//---------------------------------------------------------------------
void RefDev::UnlinkCachedTessellatorOutput(BYTE **pTempData)
{
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
{
RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
Stream.m_pData = pTempData[StreamDecl.m_dwStreamIndex];
Stream.m_pSavedData = NULL;
}
}
//---------------------------------------------------------------------
// RefDev::DrawTessQuad
//---------------------------------------------------------------------
HRESULT RefDev::DrawTessQuad( const RDBSpline &Surf, DWORD dwOffW, DWORD dwOffH, DWORD dwStride,
const unsigned *m, const unsigned *n,
double u0, double v0, double u1, double v1,
double tu0, double tv0, double tu1, double tv1,
bool bDegenerate )
{
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
for(unsigned e = 0; e < Decl.m_dwNumElements; ++e)
{
RDVElement &velem = Decl.m_VertexElements[e];
if(velem.m_bIsTessGen)
{
if((velem.m_dwToken & 0x10000000) == 0) // Check if token is D3DVSD_TESSNORMAL
{
RDVStream &vstrmin = m_VStream[velem.m_dwStreamIndexIn];
RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
LPBYTE B = vstrmin.m_pSavedData + ((dwOffH + n[0]) * dwStride + (dwOffW + m[0])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
Surf.SampleNormal(velem.m_dwDataType, u0, v0, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
Q += vstream.m_dwStride;
B = vstrmin.m_pSavedData + ((dwOffH + n[1]) * dwStride + (dwOffW + m[1])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
Surf.SampleNormal(velem.m_dwDataType, u1, v0, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
Q += vstream.m_dwStride;
B = vstrmin.m_pSavedData + ((dwOffH + n[2]) * dwStride + (dwOffW + m[2])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
Surf.SampleNormal(velem.m_dwDataType, u1, v1, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
Q += vstream.m_dwStride;
B = vstrmin.m_pSavedData + ((dwOffH + n[3]) * dwStride + (dwOffW + m[3])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
Surf.SampleNormal(velem.m_dwDataType, u0, v1, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
}
else // it is D3DVSD_TESSUV
{
RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
if(bDegenerate)
{
((FLOAT*)Q)[0] = (FLOAT)(tu0 * tv0);
((FLOAT*)Q)[1] = (FLOAT)tv0;
}
else
{
((FLOAT*)Q)[0] = (FLOAT)tu0;
((FLOAT*)Q)[1] = (FLOAT)tv0;
}
Q += vstream.m_dwStride;
if(bDegenerate)
{
((FLOAT*)Q)[0] = (FLOAT)(tu1 * tv0);
((FLOAT*)Q)[1] = (FLOAT)tv0;
}
else
{
((FLOAT*)Q)[0] = (FLOAT)tu1;
((FLOAT*)Q)[1] = (FLOAT)tv0;
}
Q += vstream.m_dwStride;
if(bDegenerate)
{
((FLOAT*)Q)[0] = (FLOAT)(tu1 * tv1);
((FLOAT*)Q)[1] = (FLOAT)tv1;
}
else
{
((FLOAT*)Q)[0] = (FLOAT)tu1;
((FLOAT*)Q)[1] = (FLOAT)tv1;
}
Q += vstream.m_dwStride;
if(bDegenerate)
{
((FLOAT*)Q)[0] = (FLOAT)(tu0 * tv1);
((FLOAT*)Q)[1] = (FLOAT)tv1;
}
else
{
((FLOAT*)Q)[0] = (FLOAT)tu0;
((FLOAT*)Q)[1] = (FLOAT)tv1;
}
}
}
else
{
RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
LPBYTE B = vstream.m_pSavedData + ((dwOffH + n[0]) * dwStride + (dwOffW + m[0])) * vstream.m_dwStride + velem.m_dwOffset;
LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
Surf.Sample(velem.m_dwDataType, u0, v0, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
Q += vstream.m_dwStride;
B = vstream.m_pSavedData + ((dwOffH + n[1]) * dwStride + (dwOffW + m[1])) * vstream.m_dwStride + velem.m_dwOffset;
Surf.Sample(velem.m_dwDataType, u1, v0, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
Q += vstream.m_dwStride;
B = vstream.m_pSavedData + ((dwOffH + n[2]) * dwStride + (dwOffW + m[2])) * vstream.m_dwStride + velem.m_dwOffset;
Surf.Sample(velem.m_dwDataType, u1, v1, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
Q += vstream.m_dwStride;
B = vstream.m_pSavedData + ((dwOffH + n[3]) * dwStride + (dwOffW + m[3])) * vstream.m_dwStride + velem.m_dwOffset;
Surf.Sample(velem.m_dwDataType, u0, v1, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
}
}
HRESULT hr;
if( m_pCurrentVShader->IsFixedFunction() )
{
//
// With declaration for Fixed Function pipeline, DX8 style
//
hr = ProcessPrimitive( D3DPT_TRIANGLEFAN, 0, 4, 0, 0 );
}
else
{
//
// Pure Vertex Shader
//
hr = ProcessPrimitiveVVM( D3DPT_TRIANGLEFAN, 0, 4, 0, 0 );
}
return hr;
}
//---------------------------------------------------------------------
// RefDev::DrawTessTri
//---------------------------------------------------------------------
HRESULT RefDev::DrawTessTri( const RDBSpline &Surf, DWORD dwOffW, DWORD dwOffH, DWORD dwStride,
const unsigned *m, const unsigned *n,
double u0, double v0, double u1, double v1, double u2, double v2,
double tu0, double tv0, double tu1, double tv1, double tu2, double tv2,
bool bDegenerate0, bool bDegenerate1, bool bDegenerate2 )
{
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
for(unsigned e = 0; e < Decl.m_dwNumElements; ++e)
{
RDVElement &velem = Decl.m_VertexElements[e];
if(velem.m_bIsTessGen)
{
if((velem.m_dwToken & 0x10000000) == 0) // Check if token is D3DVSD_TESSNORMAL
{
RDVStream &vstrmin = m_VStream[velem.m_dwStreamIndexIn];
RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
LPBYTE B = vstrmin.m_pSavedData + ((dwOffH + n[0]) * dwStride + (dwOffW + m[0])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
if(bDegenerate0)
{
Surf.SampleDegenerateNormal(velem.m_dwDataType, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
}
else
{
Surf.SampleNormal(velem.m_dwDataType, u0, v0, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
}
Q += vstream.m_dwStride;
B = vstrmin.m_pSavedData + ((dwOffH + n[1]) * dwStride + (dwOffW + m[1])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
if(bDegenerate1)
{
Surf.SampleDegenerateNormal(velem.m_dwDataType, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
}
else
{
Surf.SampleNormal(velem.m_dwDataType, u1, v1, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
}
Q += vstream.m_dwStride;
B = vstrmin.m_pSavedData + ((dwOffH + n[2]) * dwStride + (dwOffW + m[2])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
if(bDegenerate2)
{
Surf.SampleDegenerateNormal(velem.m_dwDataType, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
}
else
{
Surf.SampleNormal(velem.m_dwDataType, u2, v2, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
}
}
else // it is D3DVSD_TESSUV
{
RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
((FLOAT*)Q)[0] = (FLOAT)tu0;
((FLOAT*)Q)[1] = (FLOAT)tv0;
Q += vstream.m_dwStride;
((FLOAT*)Q)[0] = (FLOAT)tu1;
((FLOAT*)Q)[1] = (FLOAT)tv1;
Q += vstream.m_dwStride;
((FLOAT*)Q)[0] = (FLOAT)tu2;
((FLOAT*)Q)[1] = (FLOAT)tv2;
}
}
else
{
RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
LPBYTE B = vstream.m_pSavedData + ((dwOffH + n[0]) * dwStride + (dwOffW + m[0])) * vstream.m_dwStride + velem.m_dwOffset;
LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
Surf.Sample(velem.m_dwDataType, u0, v0, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
Q += vstream.m_dwStride;
B = vstream.m_pSavedData + ((dwOffH + n[1]) * dwStride + (dwOffW + m[1])) * vstream.m_dwStride + velem.m_dwOffset;
Surf.Sample(velem.m_dwDataType, u1, v1, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
Q += vstream.m_dwStride;
B = vstream.m_pSavedData + ((dwOffH + n[2]) * dwStride + (dwOffW + m[2])) * vstream.m_dwStride + velem.m_dwOffset;
Surf.Sample(velem.m_dwDataType, u2, v2, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
}
}
HRESULT hr;
if( m_pCurrentVShader->IsFixedFunction() )
{
//
// With declaration for Fixed Function pipeline, DX8 style
//
hr = ProcessPrimitive( D3DPT_TRIANGLELIST, 0, 3, 0, 0 );
}
else
{
//
// Pure Vertex Shader
//
hr = ProcessPrimitiveVVM( D3DPT_TRIANGLELIST, 0, 3, 0, 0 );
}
return hr;
}
//---------------------------------------------------------------------
// RefDev::DrawNPatch
//---------------------------------------------------------------------
HRESULT RefDev::DrawNPatch(const RDNPatch &Patch, DWORD dwStride,
const unsigned *m, const unsigned *n, unsigned segs)
{
for(unsigned i = 0; i < segs; ++i)
{
double v0 = double(i) / double(segs);
double v1 = v0;
double v2 = double(i + 1) / double(segs);
double v3 = v2;
for(unsigned j = 0; j < segs - i; ++j)
{
double u0 = double(j + 1) / double(segs);
double u1 = double(j) / double(segs);
double u2 = u1;
double u3 = u0;
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
for(unsigned e = 0; e < Decl.m_dwNumElements; ++e)
{
RDVElement &velem = Decl.m_VertexElements[e];
RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
if(velem.m_dwRegister == D3DVSDE_POSITION)
{
Patch.SamplePosition(u0, v0, (FLOAT*)Q);
Q += vstream.m_dwStride;
Patch.SamplePosition(u1, v1, (FLOAT*)Q);
Q += vstream.m_dwStride;
Patch.SamplePosition(u2, v2, (FLOAT*)Q);
if(j != segs - i - 1)
{
Q += vstream.m_dwStride;
Patch.SamplePosition(u3, v3, (FLOAT*)Q);
}
}
else
if(velem.m_dwRegister == D3DVSDE_NORMAL)
{
BYTE* B[3];
B[0] = vstream.m_pSavedData + (n[0] * dwStride + m[0]) * vstream.m_dwStride + velem.m_dwOffset;
B[1] = vstream.m_pSavedData + (n[1] * dwStride + m[1]) * vstream.m_dwStride + velem.m_dwOffset;
B[2] = vstream.m_pSavedData + (n[2] * dwStride + m[2]) * vstream.m_dwStride + velem.m_dwOffset;
Patch.SampleNormal(u0, v0, B, (FLOAT*)Q);
Q += vstream.m_dwStride;
Patch.SampleNormal(u1, v1, B, (FLOAT*)Q);
Q += vstream.m_dwStride;
Patch.SampleNormal(u2, v2, B, (FLOAT*)Q);
if(j != segs - i - 1)
{
Q += vstream.m_dwStride;
Patch.SampleNormal(u3, v3, B, (FLOAT*)Q);
}
}
else
{
BYTE *B[3];
B[0] = vstream.m_pSavedData + (n[0] * dwStride + m[0]) * vstream.m_dwStride + velem.m_dwOffset;
B[1] = vstream.m_pSavedData + (n[1] * dwStride + m[1]) * vstream.m_dwStride + velem.m_dwOffset;
B[2] = vstream.m_pSavedData + (n[2] * dwStride + m[2]) * vstream.m_dwStride + velem.m_dwOffset;
Patch.Sample(velem.m_dwDataType, u0, v0, B, Q);
Q += vstream.m_dwStride;
Patch.Sample(velem.m_dwDataType, u1, v1, B, Q);
Q += vstream.m_dwStride;
Patch.Sample(velem.m_dwDataType, u2, v2, B, Q);
if(j != segs - i - 1)
{
Q += vstream.m_dwStride;
Patch.Sample(velem.m_dwDataType, u3, v3, B, Q);
}
}
}
DWORD cVerts = (j != segs - i - 1) ? 4 : 3;
HRESULT hr;
if( m_pCurrentVShader->IsFixedFunction() )
{
//
// With declaration for Fixed Function pipeline, DX8 style
//
hr = ProcessPrimitive( D3DPT_TRIANGLEFAN, 0, cVerts, 0, 0 );
}
else
{
//
// Pure Vertex Shader
//
hr = ProcessPrimitiveVVM( D3DPT_TRIANGLEFAN, 0, cVerts, 0, 0 );
}
if(FAILED(hr))
{
return hr;
}
}
}
return S_OK;
}